亲和串
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6579 Accepted Submission(s): 2976
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
Author
Eddy
采用的是kmp算法思想,只是由于当做一个环来处理,比如前面的AABCD--->AABCDAABCD这样处理就可以了。但是用数组的话求余就可以更好的实现...
有关kmp算法,其实大部分内容还是BF算法的知识,只是添加了一个next数组,来安排匹配串t不匹配时回溯的位置,而主串是不回溯的.....
求next数组的代码:
1 void get_next(char const * pt , int * next) 2 { 3 int i,j=-1,len=strlen(pt); 4 next[i=0]=-1; 5 while(i<len) 6 { 7 if(j==-1||pt[j]==pt[i]) 8 { 9 ++i; 10 ++j; 11 if(pt[j]!=pt[i]) 12 next[i]=j; 13 else 14 next[i]=next[j]; 15 } 16 else 17 j=next[j]; 18 } 19 }
有了上面这个函数,下面的kmp部分其实就是BF算法;
代码如下:
1 //next设置为全局变量数组,当然也可以设置下面数组中... 2 int smatch_kmp(char *ps,char *pt ) 3 { 4 int lens=strlen(ps); //sizoef(pt)/sizeof(char); 5 int lent=strlen(pt); 6 int i=0,j=-1; 7 //next[] 8 get_next(ps,next); 9 while(i<lens&&j<lent) 10 { 11 if(j==-1||ps[i]==pt[j]) 12 { 13 ++i; 14 ++j; 15 } 16 else 17 j=next[j]; 18 } 19 if(j==lent) 20 return i-lent; 21 else 22 return -1; 23 24 }
所以此题的代码不难想到了为:
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //BF个改进kmp算法.... 2 /*@code龚细军*/ 3 #include<stdio.h> 4 #include<string.h> 5 #define maxn 100000 6 int next[maxn+1]; 7 char pps[maxn+1],ppt[maxn+1]; 8 /*求next数组的值*/ 9 void getnext(char const *pt ,int *next) //t表示目标串 s代表的是主串 10 { 11 int i=0,j=-1; 12 next[i]=-1; 13 int len=strlen(pt); 14 while(i<len) 15 { 16 if(j==-1||pt[i]==pt[j]) //匹配的情况,或者是开始的赋值 17 { 18 i++; 19 j++; 20 if(pt[i]!=pt[j]) //再次判断是否匹配 21 { 22 next[i]=j; 23 } 24 else 25 next[i]=next[j]; 26 } 27 else 28 j=next[j]; 29 } 30 } 31 //BF的改进kmp 32 bool smatch_kmp(char const *s ,char const *t) 33 { 34 int lens=strlen(s); //到主串的长度 35 int lent=strlen(t); //得到目标串的长度 36 memset(next,0,sizeof(next)); 37 getnext(ppt,next); 38 int i=0,j=-1; 39 while(i<2*lens&&j<lent) 40 { 41 if(j==-1||s[i%lens]==t[j]) //目前匹配所以都进位i++,j++ 42 { 43 i++; 44 j++; 45 } 46 else j=next[j]; //如果是BF的话,需要回溯,再j++ ,但是kmp在此处作出了改进,不必全回溯 47 } 48 if(j>=lent) 49 return 1; // i-lent; 说明是匹配成功了.. 50 else 51 return 0; //说面并未匹配成功 52 53 } 54 55 int main() 56 { 57 58 while(scanf("%s%s",pps,ppt)!=EOF) 59 puts(smatch_kmp(pps,ppt)==true?"yes":"no"); 60 return 0; 61 }