spoj Longest Common Substring II

来源:互联网 发布:java解析pdf文件内容 编辑:程序博客网 时间:2024/05/22 17:11

题意:求两个字符串的最长公共字串。



【分析】

每个状态记录一下它所能匹配到的最远点
公共最远点即为答案 

根据parent指针的性质:点i能接收后缀s,那么pre[i]也能接收s。

所以如果i能匹配到k位置,那么pre[i]至少也能匹配到k位置




【代码】

//spoj Longest Common Substring II #include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#define ll long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=200005;char s[mxn];int n,m,T,p,q,np,nq,len,root,tot,ans;int step[mxn],son[mxn][30],pre[mxn],mn[mxn],mx[mxn];inline void sam(){int i,j;    np=root=tot=1;    M(step),M(son),M(pre);    fo(i,1,len)    {    int c=s[i]-'a'+1;    p=np;    step[np=(++tot)]=step[p]+1;    mn[np]=mx[np]=step[np];    while(p && !son[p][c])      son[p][c]=np,p=pre[p];    if(!p){    pre[np]=root;    continue;} q=son[p][c];if(step[p]+1==step[q])  pre[np]=q;else{step[nq=(++tot)]=step[p]+1;fo(j,1,26) son[nq][j]=son[q][j];pre[nq]=pre[q];pre[q]=pre[np]=nq;mn[nq]=mx[nq]=step[nq];while(p && son[p][c]==q)  son[p][c]=nq,p=pre[p];}}}inline void find(){memset(mx,0,sizeof mx);int i,j,now=root,cnt=0;fo(i,1,len){int c=s[i]-'a'+1;if(son[now][c])  now=son[now][c],cnt++;else{while(now && !son[now][c])  now=pre[now];if(!now) now=root,cnt=0;else cnt=step[now]+1,now=son[now][c];}mx[now]=max(mx[now],cnt);}for(i=tot;i>1;i--)  mx[pre[i]]=max(mx[pre[i]],mx[i]);fo(i,2,tot)  mn[i]=min(mn[i],mx[i]);}int main(){int i,j;memset(mn,0x3f,sizeof mn);scanf("%s",s+1);len=strlen(s+1);sam();while(scanf("%s",s+1)!=EOF){len=strlen(s+1);find();}fo(i,2,tot) ans=max(ans,mn[i]);printf("%d\n",ans);return 0;}/*ahahaah*/


0 0
原创粉丝点击