cv3160 最長公共子串(SAM)
阿新 • • 發佈:2019-01-01
分析:
串建立一個
用串在上匹配
能匹配到的最遠結點(到的距離)就是最長公共子串
如果匹配不上的時候,我們直接通過跳到ta的“失配”上
tip
雖然的空間是,但是在開陣列的時候是大小要到
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=100003;
int ch[N<<1][26],fa[N<<1 ],sz=1,last=1,root=1,dis[N<<1];
char a[N],b[N];
void insert(int x)
{
int pre=last,now=++sz;
last=now;
dis[now]=dis[pre]+1;
for (;pre&&!ch[pre][x];pre=fa[pre]) ch[pre][x]=now; //找Parent樹上有沒有這個結點
if (!pre) fa[now]=root;
else
{
int q=ch[pre][x]; //找了一個祖先
if (dis[q]==dis[pre]+1) fa[now]=q;
else
{
int nows=++sz;
dis[nows]=dis[pre]+1;
memcpy(ch[nows],ch[q],sizeof(ch[nows]));
fa[nows]=fa[q]; fa[now]=fa[q]=nows;
for (;pre&&ch[pre][x]==q;pre=fa[pre]) ch[pre][x]=nows;
}
}
}
void solve()
{
int len=strlen(b+1),ans=0,now=root,tmp=0;
for (int i=1;i<=len;i++)
{
int x=b[i]-'a';
if (ch[now][x]) now=ch[now][x],tmp++;
else
{
while (now&&!ch[now][x]) now=fa[now];
if (!now) now=1,tmp=0;
else {
tmp=dis[now]+1;
now=ch[now][x];
}
}
ans=max(ans,tmp);
}
printf("%d",ans);
}
int main()
{
scanf("%s",a+1);
scanf("%s",b+1);
for (int i=1;i<strlen(a+1);i++) insert(a[i]-'a');
solve();
return 0;
}