关于后缀自动机我实在不好意思说些啥,这确实是我学过最难得算法,就到这一刻我还有点小细节没弄懂,但大体都明白了,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
",ans);
return 0;
}