SPOJ 1812 LCS2 后缀自动机
Code:
#include <cstdio> #include <algorithm> #include <cstring> #define setIO(s) freopen(s".in","r",stdin) #define maxn 30000 #define N 29 using namespace std; char str[maxn]; int n[N],id,tot=1,last=1,ans; struct SAM{ int f[maxn], ch[maxn][N],dis[maxn],C[maxn],rk[maxn],fin[maxn],mx[maxn]; void ins(int c){ int p=last,np=++tot; last=np; dis[np]=dis[p]+1;fin[np]=dis[np]; while(p&&!ch[p][c])ch[p][c]=np,p=f[p]; if(!p) f[np]=1; else{ int q=ch[p][c],nq; if(dis[q]==dis[p]+1) f[np]=q; else{ nq=++tot; dis[nq]=dis[p]+1; fin[nq]=dis[nq]; memcpy(ch[nq],ch[q],sizeof(ch[q])); f[nq]=f[q],f[q]=f[np]=nq; while(p&&ch[p][c]==q) ch[p][c]=nq,p=f[p]; } } } void update(){ int p=1,l=0; for(int i=0;i<n[id];++i){ int c=str[i]-'a'; while(p&&!ch[p][c]) p=f[p],l=dis[p]; if(ch[p][c]) mx[ch[p][c]]=max(mx[ch[p][c]],++l),p=ch[p][c]; else p=1,l=0; } for(int i=tot;i>=1;--i) { int p=rk[i]; mx[f[p]]=max(mx[f[p]],min(dis[f[p]],mx[p])); fin[p]=min(fin[p],mx[p]); mx[p]=0; } } void build(){ for(int i=1;i<=tot;++i) ++C[dis[i]]; for(int i=1;i<=tot;++i) C[i]+=C[i-1]; for(int i=1;i<=tot;++i) rk[C[dis[i]]--]=i; } void ma(){ memset(C,0,sizeof(C)); memset(rk,0,sizeof(rk)); memset(mx,0,sizeof(mx)); memset(fin,0,sizeof(fin)); memset(ch,0,sizeof(ch)); memset(f,0,sizeof(f)); memset(dis,0,sizeof(dis)); } }sam; int main(){ //setIO("input"); int cc; scanf("%d",&cc); while(cc--) { id=0; tot=last=1; ans=0; memset(n,0,sizeof(n)); sam.ma(); int uu; scanf("%d",&uu); scanf("%s",str),n[++id]=strlen(str); for(int i=0;i<n[id];++i) sam.ins(str[i]-'a'); sam.build(); for(int i=1;i<uu;++i) scanf("%s",str),n[++id]=strlen(str),sam.update(); for(int i=1;i<=tot;++i) ans=max(ans,sam.fin[i]); printf("%d\n",ans); } return 0; }