亲和串
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2427 Accepted Submission(s): 1080
Problem Description
人随着岁数的增长是越大越聪明还是越大越笨,这是一个值得全世界科学家思考的问题,同样的问题Eddy也一直在思考,因为他在很小的时候就知道亲和串如何判断了,但是发现,现在长大了却不知道怎么去判断亲和串了,于是他只好又再一次来请教聪明且乐于助人的你来解决这个问题。
亲和串的定义是这样的:给定两个字符串s1和s2,如果能通过s1循环移位,使s2包含在s1中,那么我们就说s2 是s1的亲和串。
Input
本题有多组测试数据,每组数据的第一行包含输入字符串s1,第二行包含输入字符串s2,s1与s2的长度均小于100000。
Output
如果s2是s1的亲和串,则输出"yes",反之,输出"no"。每组测试的输出占一行。
Sample Input
AABCD
CDAA
ASD
ASDF
Sample Output
yes
no
/*该题要求一个串循环后是否包含另外一个串,其实只要将母串重复一次再进行KMP匹配就行了,因为在重复母串的过程中,其实据已经将循环后的所有可能都列举出来了,比如串 "ABCD" 重复后为 "ABCDABCD" 在这个串中 "BCDA" , "CDAB" 以及 "DABC" 都相继出现了。用该种方法求解的过程中还应注意当子串长度超过母串时不进行匹配,因为那样可能输出错误的判断,比如上例中子串为 "ABCDA" 那么也会输出 yes 了。
注意 为方便 我们运用KMP算法时对于数组的输入都是从a【1】开始的
下面是我个人的代码:*/
#include<stdio.h>
#include<string.h>
char a[200005],b[100005];
int next[100005];
int d1,d2;
void get_next()
{
int i,j;
i=1;j=0;next[1]=0;
while(i<d2)
{
if(j==0||b[i]==b[j]) {i++;j++;next[i]=j;}
else j=next[j];
}
}
int KMP()
{
int i,j;
i=1;j=1;
while(i<=d1&&j<=d2)//这里我感觉好奇怪啊 我去掉等号也能AC
{
if(j==0||a[i]==b[j]) {i++;j++;}
else j=next[j];
}
if(j>=d2) return 1;
else return -1;
}
int main()
{
int i,j,ans,d;
while(gets(a+1))//这里让我长了见识啊 原来还可以这样搞 哈哈
{
gets(b+1);
d1=strlen(a+1);
/*对应的 求长度 也要从地址a+1开始 长度为d1 则一共有d1个数据 标号分别从1-2-3.。。。。d1
以前由于是从地址a开始的 如果长度为d1 一共有d1个数据 标号分别为0-----d1-1 */
d2=strlen(b+1);
if(d2>d1) {printf("no\n");continue;}
j=d1+1;//printf("1\n");
for(i=1;i<=d1;i++)
a[j++]=a[i];//把本串接到本串
a[j]='\0';
//puts(a+1);
d1=strlen(a+1);
get_next();
ans=KMP();
if(ans>0) printf("yes\n");
else printf("no\n");
}
}