亲和串

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 }


所以此题的代码不难想到了为:

代码:

HDUOJ---(2203)亲和串_HDUOJHDUOJ---(2203)亲和串_字符串_02

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 }

View Code



编程是一种快乐,享受代码带给我的乐趣!!!