后缀自动机 模板题
关于后缀自动机我实在不好意思说些啥,这确实是我学过最难得算法,就到这一刻我还有点小细节没弄懂,但大体都明白了,clj老师不愧是传奇人物,太强啦。
关于后缀数组,详细还是要看陈老师的ppt,结合网上的解释,加油。
转自:http://blog.csdn.net/thy_asdf/article/details/51569443
题目大意:
求两个串的最长公共子串
基本思路:
后缀自动机;
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 500000+10; int n,m; char a[maxn],b[maxn]; struct TSam{ int ch[maxn][26],dis[maxn],fa[maxn]; int tot,root,last; void add(int pos){ int x=a[pos]-'a',p=last,np=++tot; last=np,dis[np]=pos; for(;p&&!ch[p][x];p=fa[p]) ch[p][x]=np; if(!p) fa[np]=root; else{ int q=ch[p][x]; if(dis[q]==dis[p]+1) fa[np]=q; else{ int nq=++tot; dis[nq]=dis[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); fa[nq]=fa[q],fa[np]=fa[q]=nq; for(;ch[p][x]==q;p=fa[p]) ch[p][x]=nq; } } } }T; int main(){ scanf("%s%s",a+1,b+1); T.last=T.root=++T.tot; n=strlen(a+1),m=strlen(b+1); for(int i=1;i<=n;i++) T.add(i); int ans=0,len=0,p=T.root; for(int i=1;i<=m;i++){ int x=b[i]-'a'; if(T.ch[p][x]){ len++; p=T.ch[p][x]; } else{ while(p&&!T.ch[p][x]) p=T.fa[p]; if(!p){ p=T.root; len=0; }else{ len=T.dis[p]+1; p=T.ch[p][x]; } } ans=max(ans,len); } printf("%d\n",ans); return 0; }