http://www.spoj.com/problems/LCS/
题意:求两个串的最长公共子串
用一个串建后缀自动机,另一个串在上面类似于fail树的方式跑
不匹配时到它的parent树上的父节点,相当于保留当前最长匹配后缀
#include<cstdio> #include<cstring> using namespace std; #define N 250002 #define max(x,y) x>y ? x: y char s1[N],s2[N]; int ch[N<<1][26],fa[N<<1],tot=1; int len[N<<1]; int last=1,p,np,q,nq; void extend(int c) { len[np=++tot]=len[last]+1; for(p=last;p && !ch[p][c];p=fa[p]) ch[p][c]=np; if(!p) fa[np]=1; else { q=ch[p][c]; if(len[q]==len[p]+1) fa[np]=q; else { nq=++tot; memcpy(ch[nq],ch[q],sizeof(ch[nq])); fa[nq]=fa[q]; fa[q]=fa[np]=nq; len[nq]=len[p]+1; for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq; } } last=np; } void go() { int l=strlen(s2+1); int now=1,ans=0,now_len=0; int c; for(int i=1;i<=l;++i) { c=s2[i]-‘a‘; while(now && !ch[now][c]) { now=fa[now]; now_len=len[now]; } if(!now) { now_len=0; now=1; } else if(ch[now][c]) { now_len++; now=ch[now][c]; ans=max(ans,now_len); } } printf("%d",ans); } int main() { scanf("%s%s",s1+1,s2+1); int l=strlen(s1+1); for(int i=1;i<=l;++i) extend(s1[i]-‘a‘); go(); }