这道题只需要把原串复制一遍,然后拿另一个串去匹配就可以了。
但是作死学了下最小表示法。
http://wenku.baidu.com/link?url=disErIxplfqlFvdZy2Zy3q7FO0hYvLBqy0rFbLe93vJfNSJM5BIh4Mh3eWq0a2NPJo-09kbvFPMgyVJ07BPyNQGiw8QPCWrtPYi-RyrULDK
最小表示法是判断两个字符串是否循环同构的东西?
其实只是一种应用。
论文里写的很详细,通过一些操作得到,如果两个字符串的最小表示相同,则这两个字符串相同。
那么就是求两个字符串的最小表示。
记两个指针i,j,任意时刻它们都不能相同,记当前匹配长度为k。
如果s[i+k]=s[j+k],那么k++
如果s[i+k]>s[j+k],那么因为[i,i+k-1]与[j,j+k-1]是相同的,所以在[i,i+k-1]中不可能有最小表示,所以i+=k+1,此时k=0。
如果s[i+k]<s[j+k],那么同上。
初始时i=0,j=1就可以了。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 1000100
using namespace std;
char s[2][maxn];
int n,m;
int calc(char *s)
{
int n=strlen(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+=k+1;
else j+=k+1;
if (i==j) i++;
k=0;
}
}
return min(i,j);
}
int main()
{
scanf("%s%s",s[0],s[1]);
n=strlen(s[0]);
int j=calc(s[0]),k=calc(s[1]);
bool w=0;
for (int i=0;i<n;i++)
if (s[0][(j+i)%n]!=s[1][(k+i)%n]) {w=1;break;}
if (w) printf("No\n");
else
{
printf("Yes\n");
for (int i=0;i<n;i++) printf("%c",s[0][(j+i)%n]);
printf("\n");
}
return 0;
}