题目描述:
求两个串的最长公共子串
题目分析:
对第一个串建立SAM
第二个串讨论即可
O(nlogn)
题目链接:
OJ炸了!!!
Ac 代码:
#include <cstdio>
#include <iostream>
#include <cstring>
const int maxm=2*1e5+10;
struct node{
int fa,len;
int son[26];
}t[maxm];
int last=1,siz=1,root=1,n;
char s[maxm];
inline void extend(int c)
{
int p=last,np=++siz;
last=np;
t[np].len=t[p].len+1;
while(p&&!t[p].son[c]) t[p].son[c]=np,p=t[p].fa;
if(!p) t[np].fa=1;
else
{
int q=t[p].son[c];
if(t[p].len+1==t[q].len) t[np].fa=q;
else
{
int nq=++siz;
t[nq]=t[q];
t[nq].len=t[p].len+1;
t[q].fa=t[np].fa=nq;
while(p&&t[p].son[c]==q) t[p].son[c]=nq,p=t[p].fa;
}
}
}
int main()
{
freopen("date.in","r",stdin);
freopen("x2.out","w",stdout);
scanf("%s",s);
int len=std::strlen(s);
for(int i=0;i<len;i++) extend(s[i]-'a');
scanf("%s",s);
len=std::strlen(s);
int p=root,ans=0,xlen=0;
for(int i=0;i<len;i++)
{
int c=s[i]-'a';
if(t[p].son[c])
{
xlen++;
p=t[p].son[c];
}
else
{
while(p&&!t[p].son[c]) p=t[p].fa;
if(!p)
{
p=root,xlen=0;
}
else
{
xlen=t[p].len+1,p=t[p].son[c];
}
}
ans=std::max(ans,xlen);
}
printf("%d\n",ans);
return 0;
}