分析:
A
A
串建立一个
用
B
B
串在上匹配
能匹配到的最远结点(到
root
r
o
o
t
的距离)就是最长公共子串
如果匹配不上的时候,我们直接通过 parent p a r e n t 跳到ta的“失配”上
tip
虽然 SAM S A M 的空间是 O(n) O ( n ) ,但是在开数组的时候是大小要到 n∗2 n ∗ 2
#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;
}