大概就是后缀数组的模板题(看着0下标好累,统统改成了1下标233)
两个串中间加一个从未出现的字符分割以免连在一起形成了更大的height,然后就是对于每一个后缀查找height,若它之前的那个后缀和它不在同一个串中(sa一个大于len1,一个小于len1)即为合法情况。扫一遍就ok了。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100005;
int n,m;
int c[maxn<<1];
int s[maxn<<1];
char ss[maxn<<1];
int sa[maxn<<1],rank[maxn<<1],height[maxn<<1];
int tmp[maxn<<1],temp[maxn<<1];
void getsa()
{
int *x=tmp,*y=temp,cnt;
int m=30;
for(int i=1;i<=m;i++)c[i]=0;
for(int i=1;i<=n;i++)c[x[i]=s[i]]++;
for(int i=2;i<=m;i++)c[i]+=c[i-1];
for(int i=n;i>=1;i--)sa[c[x[i]]--]=i;
for(int k=1;k<=n;k<<=1)
{
cnt=0;
for(int i=n-k+1;i<=n;i++)y[++cnt]=i;
for(int i=1;i<=n;i++)if(sa[i]>k)y[++cnt]=sa[i]-k;
for(int i=1;i<=m;i++)c[i]=0;
for(int i=1;i<=n;i++)c[x[y[i]]]++;
for(int i=2;i<=m;i++)c[i]+=c[i-1];
for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i];
swap(x,y);
x[sa[1]]=cnt=1;
for(int i=2;i<=n;i++)
x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?cnt:++cnt;
if(cnt>=n)break;
m=cnt;
}
cnt=0;
for(int i=1;i<=n;i++)rank[sa[i]]=i;
for(int i=1;i<=n;i++)
{
if(cnt)cnt--;
int j=sa[rank[i]-1];
while(s[i+cnt]==s[j+cnt])cnt++;
height[rank[i]]=cnt;
}
}
int main()
{
scanf("%s",ss+1);
int len1=strlen(ss+1);
for(int i=1;i<=len1;i++)
s[i]=ss[i]-'a'+2;
s[len1+1]=1;
scanf("%s",ss+1);
int len2=strlen(ss+1);
for(int i=1;i<=len2;i++)
s[len1+i+1]=ss[i]-'a'+2;
n=len1+len2+1;
getsa();
int ans=0;
for(int i=1;i<=n;i++)
{
if(height[i]>ans&&((sa[i]>=len1&&sa[i-1]<len1)||(sa[i]<len1&&sa[i-1]>=len1)))
ans=height[i];
}
printf("%d",ans);
}