这道题只需要把原串复制一遍,然后拿另一个串去匹配就可以了。
但是作死学了下最小表示法。
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; }