题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1403
Longest Common Substring
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6792 Accepted Submission(s): 2401
For example:
str1 = banana
str2 = cianaic
So the Longest Common Substring is "ana", and the length is 3.
Process to the end of file.
banana cianaic
3
题解:
1.将两个字符串接在一起,并用特殊分隔符分开。然后跑一下后缀数组,得出height[]数组。
2.枚举height[]数组,如果排位相邻的两个后缀字符串的开头分别在两边(原先的两个字符串),则更新答案。
后缀数组学习推荐:
http://blog.youkuaiyun.com/yxuanwkeith/article/details/50636898
http://blog.youkuaiyun.com/j_sure/article/details/41777097
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+7;
const int MAXN = 2e5+10;
bool cmp(int *r, int a, int b, int l)
{
return r[a]==r[b] && r[a+l]==r[b+l];
}
int t1[MAXN], t2[MAXN], c[MAXN];
void DA(int str[], int sa[], int Rank[], int height[], int n, int m)
{
int i, j, p, *x = t1, *y = t2;
for(i = 0; i<m; i++) c[i] = 0;
for(i = 0; i<n; i++) c[x[i] = str[i]]++;
for(i = 1; i<m; i++) c[i] += c[i-1];
for(i = n-1; i>=0; i--) sa[--c[x[i]]] = i;
for(j = 1; j<=n; j <<= 1)
{
p = 0;
for(i = n-j; i<n; i++) y[p++] = i;
for(i = 0; i<n; i++) if(sa[i]>=j) y[p++] = sa[i]-j;
for(i = 0; i<m; i++) c[i] = 0;
for(i = 0; i<n; i++) c[x[y[i]]]++;
for(i = 1; i<m; i++) c[i] += c[i-1];
for(i = n-1; i>=0; i--) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = 1; x[sa[0]] = 0;
for(i = 1; i<n; i++)
x[sa[i]] = cmp(y, sa[i-1], sa[i], j)?p-1:p++;
if(p>=n) break;
m = p;
}
int k = 0;
for(i = 0; i<=n; i++) Rank[sa[i]] = i;
for(i = 0; i<n; i++)
{
if(k) k--;
j = sa[Rank[i]-1];
while(str[i+k]==str[j+k]) k++;
height[Rank[i]] = k;
}
}
char a[MAXN], b[MAXN];
int r[MAXN], sa[MAXN], Rank[MAXN], height[MAXN];
// sa[]下标的有效值:0~n-1; height[]下标的有效值:1~n-1
int main()
{
while(scanf("%s%s", a, b)!=EOF)
{
int lena, lenb, len;
lena = strlen(a);
lenb = strlen(b);
len = 0;
for(int i = 0; i<lena; i++) r[len++] = a[i];
r[len++] = 1;
for(int i = 0; i<lenb; i++) r[len++] = b[i];
r[len++] = 0;
DA(r, sa, Rank, height, len, 128);
int ans = 0;
for(int i = 1; i<len; i++)
if( (sa[i]<lena && sa[i-1]>lena) || (sa[i]>lena && sa[i-1]<lena) )
ans = max(ans, height[i]);
printf("%d\n", ans);
}
return 0;
}
1067



被折叠的 条评论
为什么被折叠?



