A string is finite sequence of characters over a non-empty finite set Σ.
In this problem, Σ is the set of lowercase letters.
Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.
Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.
Here common substring means a substring of two or more strings.
Input
The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.
Output
The length of the longest common substring. If such string doesn't exist, print "0" instead.
Example
Input:
alsdfkjfjkdsal
fdjskalajfkdsla
aaaajfaaaa
Output:
2
Notice: new testcases added
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
后缀自动机~
推荐两篇博客:那篇俄罗斯文章的翻译,一篇神奇的双语总结~
以及陈老师的PPT~
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 200001
int len,tot,cnt,s[maxn],l[maxn],cl[maxn],mn[maxn],fa[maxn],to[maxn][26],v[maxn],ans;
char ch[100001];
struct sam{
int p,q,np,nq,la;
sam(){
cnt=++la;
}
void ext(int u)
{
p=la;la=np=++cnt;l[np]=l[p]+1;
for(;p && !to[p][u];p=fa[p]) to[p][u]=np;
if(!p) fa[np]=1;
else
{
q=to[p][u];
if(l[p]+1==l[q]) fa[np]=q;
else
{
nq=++cnt;l[nq]=l[p]+1;
memcpy(to[nq],to[q],sizeof(to[q]));
fa[nq]=fa[q];fa[np]=fa[q]=nq;
for(;to[p][u]==q;p=fa[p]) to[p][u]=nq;
}
}
}
void build()
{
scanf("%s",ch);
len=strlen(ch);
for(int i=0;i<len;i++) ext(ch[i]-'a');
}
bool pre()
{
if(scanf("%s",ch)==EOF) return 0;
len=strlen(ch);
memset(cl,0,sizeof(cl));
int tmp=0;
for(int p=1,i=0;i<len;i++)
{
int c=ch[i]-'a';
if(to[p][c]) p=to[p][c],tmp++;
else
{
while(p && !to[p][c]) p=fa[p];
if(!p) p=1,tmp=0;
else tmp=l[p]+1,p=to[p][c];
}
cl[p]=max(cl[p],tmp);
}
for(int i=cnt;i;i--)
{
int t=s[i];
mn[t]=min(mn[t],cl[t]);
if(fa[t] && cl[t]) cl[fa[t]]=l[fa[t]];
}
return 1;
}
}sam;
int main()
{
sam.build();
for(int i=1;i<=cnt;i++) mn[i]=l[i],v[l[i]]++;
for(int i=1;i<=len;i++) v[i]+=v[i-1];
for(int i=1;i<=cnt;i++) s[v[l[i]]--]=i;
while(sam.pre());
for(int i=1;i<=cnt;i++) ans=max(ans,mn[i]);
printf("%d\n",ans);
return 0;
}