#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define maxc 27 //字符集的大小 a~z
#define maxs 250005 //字符串大小
#define smax 500005 //自动机上的状态数,应该开到两倍的字符串长度
#define mem(a) memset(a,0,sizeof(a))
#define f(c,a,b) for(int c=a; c<=b; c++)
using namespace std;
typedef long long ll;
char a[maxs], b[maxs];
int sl, size, last, sb, ans; //字符串长度,状态数,上一次extend完的那个状态
int to[smax][maxc]; //trans,转移函数
int mal[smax], link[smax]; //一个状态表示的最大长度的串,后缀链接
//一个状态表示的最小长度的串就等于它后缀链接的那个mal-1
void init(){
mem(to); mem(mal); mem(link);
last = size = 1; //SAM的开始节点为1
sl = strlen(a);
sb = strlen(b);
ans = 0;
}
void extend(int c){
int p, cur=++size;
mal[cur] = mal[last] + 1;
//情况一,前面的指向都为空
for(p=last; p&&!to[p][c]; p=link[p]) to[p][c] = cur;
if(!p) link[cur] = 1;
else{
int q = to[p][c]; //到状态q后面不为空
//情况二A,这个状态的maxlen 正好和当前需要的一致
if(mal[q] == mal[p] + 1) link[cur] = q;
else{ //情况二B,需要拆分这个状态
int cl = ++size; //克隆一个用来装短的部分
mal[cl] = mal[p] + 1;
memcpy(to[cl], to[q], sizeof(to[q]));
link[cl] = link[q];
while(p && to[p][c] == q){
to[p][c] = cl;
p = link[p];
}
link[cur] = link[q] = cl;
}
}
last = cur;
}
void lcs(){
int p=1, nl=0;
f(i,0,sb-1){
while( !to[p][b[i]-'a'] && p ) {
p = link[p];
nl = mal[p];
}
if(p) {
nl++;
p = to[p][b[i]-'a'];
ans = max( ans, nl );
//cout<<i<<' '<<p<<' '<<mal[p]<<endl;
}else { p=1; nl=0; }
}
}
int main(){
//freopen("owo.in","r",stdin);
scanf("%s%s", a, b);
init();
f(i,0,sl-1) extend(a[i]-'a');
lcs();
cout<<ans<<endl;
return 0;
}
rt。。。为什么呀1551,quq求大佬帮助