caioj1472: 后缀自动机1:多个串的LCS
子串母串跑合并答案
一个点的fail的dep是比任意一条根到这个点路径长度要小的。
那么改就可以直接来了。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int len,a[2100]; struct SAM { int w[30],dep,fail; }ch[2100];int cnt,last; void insert(int dep,int x) { int pre=last,now=++cnt; ch[now].dep=dep; last=now; while(pre!=0&&ch[pre].w[x]==0) ch[pre].w[x]=now, pre=ch[pre].fail; if(pre==0)ch[now].fail=1; else { int nxt=ch[pre].w[x]; if(ch[nxt].dep==ch[pre].dep+1)ch[now].fail=nxt; else { int nnxt=++cnt; ch[nnxt]=ch[nxt]; ch[nnxt].dep=ch[pre].dep+1; ch[now].fail=ch[nxt].fail=nnxt; while(pre!=0&&ch[pre].w[x]==nxt) ch[pre].w[x]=nnxt, pre=ch[pre].fail; } } } int Rsort[2100],sa[2100]; void sssort() { for(int i=1;i<=cnt;i++)Rsort[ch[i].dep]++; for(int i=1;i<=len;i++)Rsort[i]+=Rsort[i-1]; for(int i=cnt;i>=1;i--)sa[Rsort[ch[i].dep]--]=i; } int f[2100],g[2100]; void solve() { int now=1,L=0; memset(f,0,sizeof(f)); for(int i=1;i<=len;i++) { int x=a[i]; while(now!=1&&ch[now].w[x]==0) now=ch[now].fail, L=ch[now].dep; if(ch[now].w[x]!=0) { L++; now=ch[now].w[x]; f[now]=max(f[now],L); } } for(int i=cnt;i>=2;i--) { int x=sa[i],y=ch[sa[i]].fail; f[y]=min(ch[y].dep,max(f[y],f[x])); } for(int i=1;i<=cnt;i++)g[i]=min(g[i],f[i]); } char ss[2100]; int main() { scanf("%s",ss+1);len=strlen(ss+1); cnt=last=1; ch[1].dep=0; for(int i=1;i<=len;i++) a[i]=ss[i]-'a'+1, insert(i,a[i]); sssort(); memset(g,63,sizeof(g)); while(scanf("%s",ss+1)!=EOF) { len=strlen(ss+1); for(int i=1;i<=len;i++)a[i]=ss[i]-'a'+1; solve(); } int ans=0; for(int i=1;i<=cnt;i++)ans=max(ans,g[i]); if(ans<=3)printf("They are too short!\n"); else printf("True\n%d\n",ans); return 0; }
pain and happy in the cruel world.