题目:
循环移位(Cycle)
描述
所谓循环移位是指。一个字符串的首字母移到末尾, 其他字符的次序保持不变。比如ABCD经过一次循环移位后变成BCDA
给定两个字符串,判断它们是不是可以通过若干次循环移位得到彼此
输入
由m行组成,每行包含两个由大写字母'A'~'Z'组成的字符串,中间由空格隔开
输出
对于每行输入,输出这两个字符串是否可以通过循环移位得到彼此:YES表示是,NO表示否
Example
Input
AACD CDAA
ABCDEFG EFGABCD
ABCD ACBD
ABCDEFEG ABCDEE
Output
YES
YES
NO
NO
分析:
首先抓住本题的一个细节,“得到彼此”,不难得出,两个串长不相等则输出“NO”。接着考察循环移位算法和匹配算法,其中循环移位算法不难写出,匹配算法可用KMP算法,然而使用此二算法一般会导致使用暴力解法,除此之外是否有好的方法?确实有,不过不需要循环移位算法,其思想是串A接串A得到AA,当串B是AA的子串时,匹配成功,这个方法非常巧妙,若没有一定的思维含量是很难想到的,我认为其出发点在于寻找规律。
代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXSIZE 100000
int* bulidNext(char* P,int m){
int *N=(int*)malloc(m*sizeof(int));
int j=0,t=N[0]=-1;
while(j<m-1){
if(t<0||P[j]==P[t]){
j++;t++;
N[j]=(P[j]!=P[t]?t:N[t]);
}
else t=N[t];
}
return N;
}
int KMP(char* P,char* T,int n,int m){
int i=0,j=0;
int *next=bulidNext(P,m);
while(i<n&&j<m){
if(j<0||T[i]==P[j]){i++;j++;}
else j=next[j];
}
return i-j;
}
int main(){
char T[2*MAXSIZE],P[MAXSIZE];
while(scanf("%s %s",T,P)!=EOF){
int n=strlen(T),m=strlen(P);
if(n!=m)puts("NO");
else{
int i,j=0;
for(i=n;i<2*n;i++)
T[i]=T[j++];
n*=2;
if(KMP(P,T,n,m)<=n-m)puts("YES");
else puts("NO");
}
}
return 0;
}