考虑直接枚举所有不同的串
A
A
A(显然是初始串的子串)。
若我们预处理出任意两个后缀的LCP,对于一个固定的串
A
A
A,我们容易在
O
(
c
o
u
n
t
(
A
)
)
\mathcal O(count(A))
O(count(A))(
A
A
A在初始串中的出现次数)的时间复杂度内判定是否有合法方案。注意到
∑
A
c
o
u
n
t
(
A
)
=
O
(
l
e
n
2
)
\sum_{A}count(A)=\mathcal O(len^2)
∑Acount(A)=O(len2),于是我们暴力枚举即可。
时间复杂度为
O
(
l
e
n
2
)
\mathcal O(len^2)
O(len2)。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
char s1[2005],s2[2005];
int lcp1[2005][2005],lcp2[2005][2005],lcp3[2005][2005];
int nxt[2005][2005];
bool fir[2005][2005];
int pos[2005];
int main() {
freopen("curiosity.in","r",stdin);
freopen("curiosity.out","w",stdout);
cin.getline(s1+1,10000);
cin.getline(s2+1,10000);
int n=strlen(s1+1),m=strlen(s2+1);
for(int i=n;i>0;i--)
for(int j=n;j>=i;j--) lcp1[i][j]=((s1[i]==s1[j])?lcp1[i+1][j+1]+1:0);
for(int i=m;i>0;i--)
for(int j=m;j>=i;j--) lcp2[i][j]=((s2[i]==s2[j])?lcp2[i+1][j+1]+1:0);
for(int i=n;i>0;i--)
for(int j=m;j>0;j--) lcp3[i][j]=((s1[i]==s2[j])?lcp3[i+1][j+1]+1:0);
for(int i=1;i<=n;i++) {
int k=0;
for(int j=i-1;j>0;j--)
while (k<lcp1[j][i]) nxt[j][++k]=i;
while (k<=n-i) fir[i][++k]=1;
}
int ans1=inf,ans2=inf,id=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n-i+1;j++)
if (fir[i][j]) {
int sz=0;
for(int k=i;k;k=nxt[k][j])
if (!sz||k>=pos[sz]+j) pos[++sz]=k;
pos[sz+1]=n+1;
if (n-sz*j>m||(m-(n-sz*j))%sz!=0) continue;
int d=(m-(n-sz*j))/sz;
if (pos[1]>1&&lcp3[1][1]<pos[1]-1) continue;
bool ok=1;
int r=pos[1];
for(int k=1;k<=sz;k++) {
if (lcp2[pos[1]][r]<d) {
ok=0;
break;
}
r+=d;
if (lcp3[pos[k]+j][r]<pos[k+1]-(pos[k]+j)) {
ok=0;
break;
}
r+=pos[k+1]-(pos[k]+j);
}
if (ok&&j<ans1) {
ans1=j;
ans2=d;
id=i;
}
}
printf("s/");
for(int i=0;i<ans1;i++) putchar(s1[id+i]);
printf("/");
for(int i=0;i<ans2;i++) putchar(s2[id+i]);
printf("/g\n");
return 0;
}
/*
abababa
cbc
*/