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 simple, for two 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 exactly two lines, each line consists of no more than 250000 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
Output:
3
Notice: new testcases added
dp是onlogn, 后缀自动机是on
用第一个串创自动机
用第二个串进行匹配
就是如果当前串匹配到这个点,当nxt[p][c]存在,那么 len++;
否则找到上一个具有同样终点的串同时存在nxt[p][c],如果找到,因为是fail串,所以必定max[i]长度比当前长度小,而且必定是当前串的后缀,所以直接取len=Max[p]+1,如果不存在,len=0.由于你是顺着nxt[p][c]走的,所以走到的点必定是已经匹配的公共子串长度,但是是每次都len++,而不是len=Max[p]+1,因为你虽然走到这个点,只是代表这个串出现的位置的集合,而Max是集合里面的最长串,所以是len++,而fail那里,是因为fail集合里面的最长的串也是匹配了的串的后缀,所以。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=550000+5;
int last=1,tail=1,in[maxn],Min[maxn];
int Max[maxn],cnt[maxn],sum[maxn],vis[maxn];
int nxt[maxn][26],fail[maxn];
char sa[maxn],sb[maxn];
inline void build(char *s)
{
while(*s)
{
int p=last,t=++tail,c=*s++-'a';
Max[t]=Max[p]+1;
while(p&&!nxt[p][c])
nxt[p][c]=t,p=fail[p];
if(p)
{
int q=nxt[p][c];
if(Max[q]==Max[p]+1)
fail[t]=q,Min[t]=Max[q]+1;
else
{
int k=++tail;
fail[k]=fail[q];
fail[t]=fail[q]=k;
Max[k]=Max[p]+1;
memcpy(nxt[k],nxt[q],sizeof(nxt[q]));
while(p&&nxt[p][c]==q)
nxt[p][c]=k,p=fail[p];
}
}
else
fail[t]=Min[t]=1;
last=t;
}
}
int main()
{
while(~scanf("%s %s",sa,sb))
{
last=1,tail=1;
build(sa);
int h=strlen(sb);
int p=1;
int len=0,ans=0;
for(int i=0;i<h;i++)
{
int x=sb[i]-'a';
if(nxt[p][x])
{
len++;
p=nxt[p][x];
}
else
{
while(p&&!nxt[p][x])
p=fail[p];
if(!p) p=1,len=0;
else len=Max[p]+1,p=nxt[p][x];
}
ans=max(ans,len);
}
printf("%d\n",ans );
}
}