【题目大意】
构造第一个串的后缀自动机,用第二个串与其逐位匹配。
记录当前匹配到的位置p和位数len,如果下一个字符c仍能匹配成功,则更新匹配位置p=p.go[c]、匹配位数len++,否则沿后缀链接跳转至第一个能够接受c的位置q,令len=q.step。
【代码】
/************************
ID:Ciocio
LANG:C++
DATE:2014-1-28
TASK:LCS
************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define MAXN 250010
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rrep(i,a,b) for(int i=a;i>=b;--i)
char A[MAXN],B[MAXN];
struct SAM{
int tot,last;
int go[MAXN<<1][26],pre[MAXN<<1],step[MAXN<<1];
void new_node(int s){
step[++tot]=s;
pre[tot]=0;
memset(go[tot],0,sizeof go[tot]);
}
void build(char* s){
tot=0;last=1;
new_node(0);
int n=strlen(s);
rep(i,0,n-1){
new_node(step[last]+1);
int c=s[i]-'a';
int p=last,np=tot,q,nq;
for(;p&&!go[p][c];p=pre[p]) go[p][c]=np;
if(!p)
pre[np]=1;
else{
q=go[p][c];
if(step[q]==step[p]+1) pre[np]=q;
else{
new_node(step[p]+1);
nq=tot;
memcpy(go[nq],go[q],sizeof go[q]);
pre[nq]=pre[q];
pre[np]=
pre[q]=nq;
for(;p&&go[p][c]==q;p=pre[p]) go[p][c]=nq;
}
}
last=np;
}
}
int match(char* s){
int p=1,len=0,res=0;
int n=strlen(s);
rep(i,0,n-1){
int c=s[i]-'a';
while(pre[p]&&!go[p][c]){
p=pre[p];
len=step[p];
}
if(go[p][c]){
p=go[p][c];
len++;
}
res=max(res,len);
}
return res;
}
};
SAM run;
int main(){
scanf("%s%s",A,B);
run.build(A);
cout<<run.match(B)<<endl;
return 0;
}