您的位置:首页 > 其它

hdu_1403_Longest Common Substring(后缀数组的应用)

2016-08-03 17:18 405 查看

题目链接:hdu_1403_Longest Common Substring

题意:

给你两个字符串,然你找最长的公共子串

题解:

后缀数组的经典应用,要找两个字符串的公共子串,那么就相当于找两个串的后缀的最长公共前缀,我们将两个字符串拼接在一起,中间插一个特殊字符

然后我们考虑height数组,height数组存的是排i和i-1的最长前缀,如果sa[i]和sa[i-1]在特殊字符的两边,那么这个height[i]记录的就是这两个串的最长

子串,然后扫一遍height数组更新一下答案就行了

#include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;++i)
using namespace std;

namespace suffixarray{
#define FN(n) for(int i=0;i<n;i++)
const int N =2E5+7;//字符串长度
int rnk
,sa
,height
,c
;char s
;
void getsa(int n,int m,int *x=rnk,int *y=height){
FN(m)c[i]=0;FN(n)c[x[i]=s[i]]++;FN(m)c[i+1]+=c[i];
for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
for(int k=1,p;p=0,k<=n;k=p>=n?N:k<<1,m=p){
for(int i=n-k;i<n;i++)y[p++]=i;
FN(n)if(sa[i]>=k)y[p++]=sa[i]-k;
FN(m)c[i]=0;FN(n)c[x[y[i]]]++;FN(m)c[i+1]+=c[i];
for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
swap(x,y),p=1,x[sa[0]]=0;
for(int i=1;i<n;i++)
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
}
FN(n)rnk[sa[i]]=i;
for(int i=0,j,k=0;i<n-1;height[rnk[i++]]=k)
for(k=k?k-1:k,j=sa[rnk[i]-1];s[i+k]==s[j+k];k++);
}
}
using namespace suffixarray;
int main(){
while(~scanf("%s",s))
{
int len=strlen(s),sz;
s[len]='$';
scanf("%s",s+len+1);
sz=strlen(s),getsa(sz+1,128);
int ans=0;
F(i,1,sz)if(ans<height[i]&&(sa[i]-len)*(sa[i-1]-len)<0)ans=height[i];
printf("%d\n",ans);
}
return 0;
}
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: