POJ 2774 (后缀数组 最长公共字串) Long Long Message

用一个特殊字符将两个字符串连接起来,然后找最大的height,而且要求这两个相邻的后缀的第一个字符不能在同一个字符串中。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5
 6 const int maxn = 200000 + 10;
 7
 8 char s[maxn];
 9 int n;
10 int sa[maxn], rank[maxn], height[maxn];
11 int t[maxn], t2[maxn], c[maxn];
12
13 void build_sa(int n, int m)
14 {
15     int i, *x = t, *y = t2;
16     for(i = 0; i < m; i++) c[i] = 0;
17     for(i = 0; i < n; i++) c[x[i] = s[i]]++;
18     for(i = 1; i < m; i++) c[i] += c[i - 1];
19     for(i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
20     for(int k = 1; k <= n; k <<= 1)
21     {
22         int p = 0;
23         for(i = n - k; i < n; i++) y[p++] = i;
24         for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
25         for(i = 0; i < m; i++) c[i] = 0;
26         for(i = 0; i < n; i++) c[x[y[i]]]++;
27         for(i = 1; i < m; i++) c[i] += c[i - 1];
28         for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
29         swap(x, y);
30         p = 1; x[sa[0]] = 0;
31         for(i = 1; i < n; i++)
32             x[sa[i]] = y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k] ? p - 1 : p++;
33         if(p >= n) break;
34         m = p;
35     }
36 }
37
38 void build_height()
39 {
40     int k = 0;
41     for(int i = 1; i <= n; i++) rank[sa[i]] = i;
42     for(int i = 0; i < n; i++)
43     {
44         if(k) k--;
45         int j = sa[rank[i] - 1];
46         while(s[i + k] == s[j + k]) k++;
47         height[rank[i]] = k;
48     }
49 }
50
51 int main()
52 {
53     //freopen("in.txt", "r", stdin);
54
55     scanf("%s", s);
56     int pos = strlen(s);
57     s[pos] = 1;
58     scanf("%s", s + pos + 1);
59     n = strlen(s);
60
61     build_sa(n + 1, 256);
62     build_height();
63
64     int ans = 0;
65     for(int i = 2; i <= n; i++)
66     {
67         if(height[i] > ans)
68         {
69             if((sa[i]>pos && sa[i-1]<pos) || (sa[i]<pos&&sa[i-1]>pos))
70                 ans = height[i];
71         }
72     }
73
74     printf("%d\n", ans);
75
76     return 0;
77 }

代码君

时间: 2024-08-09 02:08:48

POJ 2774 (后缀数组 最长公共字串) Long Long Message的相关文章

[poj 2274]后缀数组+最长公共子序列

题目链接:http://poj.org/problem?id=2774 后缀数组真的太强大了,原本dp是n^2的复杂度,在这里只需要O(n+m). 做法:将两个串中间夹一个未出现过的字符接起来,然后做一次后缀数组,得到的height相邻两个排名的后缀,在串中的位置如果满足在分界符左右两侧,就更新最长公共前缀.最后得到的最大值就是最长公共子序列. #include<algorithm> #include<cstdio> #include<cstring> using na

POJ 2217 (后缀数组+最长公共子串)

题目链接: http://poj.org/problem?id=2217 题目大意: 求两个串的最长公共子串,注意子串是连续的,而子序列可以不连续. 解题思路: 有个炒鸡快的O(n)的Manacher算法.不过只能求裸的最长公共和回文子串. 后缀数组解法是这类问题的模板解法. 对于n个串的最长公共子串,这要把这些串连在一起,中间用"$"这类的特殊符号分隔一下. 先求后缀数组,再求最长公共前缀,取相邻两个且属于不同串的sa的最大LCP即可. 原理就是:这样把分属两个串的LCP都跑了一遍,

POJ 2774 后缀数组:求最长公共子串

思路:其实很简单,就是两个字符串连接起来,中间用个特殊字符隔开,然后用后缀数组求最长公共前缀,然后不同在两个串中,并且最长的就是最长公共子串了. 注意的是:用第一个字符串来判断是不是在同一个字符中,刚开始用了第二个字符的长度来判断WA了2发才发现. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<

URAL 1517 Freedom of Choice(后缀数组,最长公共字串)

题目 输出最长公共字串 #define maxn 200010 int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; int cmp(int *r,int a,int b,int l) {return r[a]==r[b]&&r[a+l]==r[b+l];}//yuan lai zhi qian ba zhe li de l cuo dang cheng 1 le ... void da(int *r,int *sa,int n,int m) { int i,j

最长递归子序列、最长公共字串、最长公共子序列、编辑距离

[TOC]   ### 最长递归子序列 #### 题目 给定数组arr,返回arr中的最长递增子序列,如`arr=[2,1,5,3,6,4,8,9,7]`,返回的最长递增子序列为`[1,3,4,8,9]` #### 题解思路 先用DP来求解子序列递增的最大长度,如arr的长度序列为`dp=[1,1,2,2,3,3,4,5,4]`,然后对这个长度序列dp从右到左遍历,得到最长递增子序列. 1. 求解长度序列,令dp[i]表示在以arr[i]这个数结尾的情况下,arr[0...i]中的最大递增子序列

【编程题目】最长公共字串

56.最长公共字串(算法.字符串).题目:如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中,则字符串一称之为字符串二的子串.注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中.请编写一个函数,输入两个字符串,求它们的最长公共子串,并打印出最长公共子串.例如:输入两个字符串 BDCABA 和 ABCBDAB,字符串 BCBA 和 BDAB 都是是它们的最长公共子串,则输出它们的长度 4,并打印任意一个子串. 经典动态规划题. #include <stdio.h> #i

搜索里的相似度计算-最长公共字串

相似度计算的任务是根据两段输入文本的相似度返回从0到1之间的相似度值:完全不相似,则返回0,:完全相同,返回1.衡量两端文字距离的常用方法有:海明距离(Hamming distance),编辑距离,欧氏距离,文档向量的夹角余弦距离,最长公共字串. 1. 余弦相似度 把两篇文档看作是词的向量,如果x,y为两篇文档的向量,则:Cos(x, y) = (x * y) / (||x|| * ||y||) 使用Hashmap可以很方便的把这个计算出来 2. 最长公共字串(Longest Common Su

最长公共子序列与最长公共字串

显然最长公共子序列不一定需要连续的,只要字符的顺序严格递增即可.最长公共字串需要字符连续 子序列代码: package test; import java.util.*; /* * 本题是求最长公共子序列,子序列未必连续,只需要严格递增即可 * 如 abcdeeeeeeeee和atttbggcd 最长公共子序列为abcd 长度为4 * * */ public class Main4{ public static void main(String... args){ try(Scanner in

POJ 2774 后缀数组

题目链接:http://poj.org/problem?id=2774 题意:给定两个只含小写字母的字符串,求字符串的最长公共子串长度. 思路:根据<<后缀数组——处理字符串的有力工具>>的思路,字符串的任何一个子串都是这个字符串的某个后缀的前缀 .求 A和 B的最长公共子串等价于求 A的后缀和 B的后缀的最长公共前缀的最大值. 如果枚举 A 和 B的所有的后缀,那么这样做显然效率低下.由于要计算 A的后缀和 B的后缀的最长公共前缀, 所以先将第二个字符串写在第一个字符串后面, 中