题目等价于求给定两个长度都为
n
n
的串,求一个最大的
L
L
使得与
B1..L
B
1..
L
循环同构。
我们先对
A,B
A
,
B
互相做一遍扩展KMP,记
Ai..n
A
i
.
.
n
与
B
B
的LCP为,
exb
e
x
b
同理。
循环同构一定是存在
x
x
,使得,我们枚举
x
x
,那么就是要在找到最大的满足
exbp≥x
e
x
b
p
≥
x
中,也就找到了一个
L=x+p
L
=
x
+
p
。
我们用一个类似并查集的方法来维护这个,设
fai
f
a
i
为
i
i
左边第一个合法的,考虑到
x
x
是递增的,如果某个就把
j
j
<script type="math/tex" id="MathJax-Element-2216">j</script>缩掉即可。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 2000010
using namespace std;
int n,nxta[N],nxtb[N],exa[N],exb[N],fa[N];
char a[N],b[N];
void ex_kmp(char s[],char t[],int nxt[],int ex[])
{
int st=1,ed=0;
nxt[1]=n;
for(int i=2;i<=n;i++)
{
if(nxt[i-st+1]<ed-i+1) {nxt[i]=nxt[i-st+1];continue;}
ed=max(i-1,ed);
for(int j=ed-i+1;ed<n&&t[ed+1]==t[j+1];ed++,j++);
st=i;nxt[i]=ed-i+1;
}
st=1;ed=0;
for(int i=1;i<=n;i++)
{
if(nxt[i-st+1]<ed-i+1) {ex[i]=nxt[i-st+1];continue;}
ed=max(i-1,ed);
for(int j=ed-i+1;ed<n&&s[ed+1]==t[j+1];ed++,j++);
st=i;ex[i]=ed-i+1;
}
}
int getfa(int v,int x)
{
if(!v||exb[v]>=x) return v;
return (fa[v]=getfa(fa[v],x));
}
int main()
{
scanf("%d%s%s",&n,a+1,b+1);
ex_kmp(a,b,nxtb,exa);
ex_kmp(b,a,nxta,exb);
for(int i=1;i<=n;i++)
fa[i]=i-1;
int ans=0;
for(int i=1;i<=n;i++)
{
int tmp=getfa(exa[i+1]+1,i);
//cout<<i<<' '<<tmp<<endl;
if(tmp) ans=max(ans,tmp+i-1);
}
printf("%d",ans);
return 0;
}