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
题解:这里是一个子串匹配的问题
首先我们把第一个串建SAM,然后用第二个串进行去匹配。设当前长度为len,如果匹配就继续往下,len++。如果不匹配了就要跳fa,直到跳到有这个出边了即可。有两种情况。
第一种情况:跳到根了,我们要重置len。继续匹配下去。
第二种情况:那我们就沿p的fa不断走直到发现有c这个转移位置,len变为len[p]+1(相当于我知道B串的某一部分已经在A串中匹配,现在下一位无法匹配,我就不断取B串的后缀直到发现下一位可以匹配)。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct node
{
int len,fa;
int ch[26];
node(){memset(ch,0,sizeof(ch));len=0;}
}dian[N<<1];
string s,s1;
int las=1,tot=1;
void add(int c)
{
int p=las;
int np=las=++tot;
dian[np].len=dian[p].len+1;
for(;p&&!dian[p].ch[c];p=dian[p].fa) dian[p].ch[c]=np;
if(!p) dian[np].fa=1;
else
{
int q=dian[p].ch[c];
if(dian[q].len==dian[p].len+1) dian[np].fa=q;
else
{
int nq=++tot;
dian[nq]=dian[q];
dian[nq].len=dian[p].len+1;
dian[q].fa=dian[np].fa=nq;
for(;p&&dian[p].ch[c]==q;p=dian[p].fa) dian[p].ch[c]=nq;
}
}
}
int main()
{
cin>>s>>s1;
for(int i=0;i<s.size();i++) add(s[i]-'a');
int len=0;
int p=1;
int res=0;
for(int i=0;i<s1.size();i++)
{
int c=s1[i]-'a';
if(dian[p].ch[c]) {len++;p=dian[p].ch[c];} //如果匹配成功,那就继续往下匹配,len++
else
{
for(;p&&!dian[p].ch[c];p=dian[p].fa);//发生了失配,我们我要跳fa,跳到我们之前匹配好的后缀上
if(!p) p=1,len=0;//如果跳到根了,那么就要重新来了
//相当于我知道B串的某一部分已经在A串中匹配,现在下一位无法匹配,我就不断取B串的后缀直到发现下一位可以匹配
else len=dian[p].len+1,p=dian[p].ch[c]; //如果跳到了之前已经有后缀的上面,那么长度自然等于当前节点的长度+1
}
res=max(res,len);
}
printf("%d\n",res);
}