题意
就是问你两个字符串是不是同构的。。
题解
明显地最小表示法啊。。
当然,你把一个串倍长一份来做也可以
用KMP还是可以得到一个O(n)的做法
但这里作为一个最小表示法的板子题,还是用一下最小表示法吧
最小表示法
O(nlogn)的做法
吧字符串倍长一下暴力hash一下
记录一个当前答案的端点
然后往右扫就可以了比较就用hash加速
O(n)的做法
其实思路也十分简单
维护两个可能可以的端点i,j
维护一个k,表示最长公共前缀、
如果
s(i+k)=s(j+k)
s
(
i
+
k
)
=
s
(
j
+
k
)
,那么
k++
k
+
+
否则,根据大小,使得
i=i+k+1
i
=
i
+
k
+
1
,或者
j=j+k+1
j
=
j
+
k
+
1
代码也很好写:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1000005;
char ss[2][N];
int n;
int get (char *s)
{
int i=0,j=1,k=0;
while (i<n&&j<n&&k<n)
{
if (s[(i+k)%n]==s[(j+k)%n]) k++;
else
{
if (s[(i+k)%n]>s[(j+k)%n]) i=i+k+1;
else j=j+k+1;
if (i==j) i++;
k=0;
}
}
return min(i,j);
}
int main()
{
scanf("%s%s",ss[0],ss[1]);
n=strlen(ss[0]);
int j=get(ss[0]),k=get(ss[1]);
bool tf=true;
for (int u=0;u<n;u++)
if (ss[0][(u+j)%n]!=ss[1][(u+k)%n])
{
tf=false;
break;
}
if (tf==false) printf("No\n");
else
{
printf("Yes\n");
for (int u=0;u<n;u++)
printf("%c",ss[0][(u+j)%n]);
}
return 0;
}