两串旋转问题(KMP)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了两串旋转问题(KMP)相关的知识,希望对你有一定的参考价值。

如果对于一个字符串A,将A的前面任意一部分挪到后边去形成的字符串称为A的旋转词。比如A="12345",A的旋转词有"12345","23451","34512","45123"和"51234"。对于两个字符串A和B,请判断A和B是否互为旋转词。

给定两个字符串AB及他们的长度lenalenb,请返回一个bool值,代表他们是否互为旋转词。

测试样例:
"cdab",4,"abcd",4
返回:true

题目解析:针对测试用例来说,利用KMP判断“cdabcdab"中是否含有子串"abcd",因为任意串自身连接包含所有旋转可能。

一般KMP的C++实现如下:
 1 #include<iostream>
 2 #include<string.h>
 3 using namespace std;
 4 char str1[80];
 5 char str2[80];
 6 int next[80];
 7 
 8 
 9 void GetNext(char* p,int next[]){    
10     int pLen = strlen(p);    
11     next[0] = -1;    
12     int k = -1;    
13     int j = 0;    
14     while (j < pLen - 1){    
15        //p[k]表示前缀,p[j]表示后缀    
16         if (k == -1 || p[j] == p[k]){    
17             ++k;    
18             ++j;    
19             next[j] = k;    
20         }    
21         else k = next[k];    
22     }    
23 }    
24 
25 int KMP(char *pattern,char *str){//判断是否存在子串 
26     int i,j;
27     int plen=strlen(pattern);
28     int len=strlen(str);
29     for(i=0;i<len;){
30         for(j=0;j<plen;j++){
31             if(str[i+j]!=pattern[j])
32             break;
33         }
34         if(j==plen)
35         return 1; 
36         i+=j-next[j];
37     }
38     return 0;
39 }
40 
41 int main(){
42     cin.getline(str1,80);
43     cin.getline(str2,80);
44     GetNext(str2,next);
45     if(KMP(str2,str1)){
46         cout<<"匹配成功!";
47     }
48     return 0;
49 }
C++中string有+算符重载的连接功能。按题意修改算法原型,得到初步结果如下(输入输出格式未调整):
输入:cdab
   abcd
输出:true
 1 #include<iostream>
 2 #include<string.h>
 3 using namespace std;
 4 int next[80];
 5 
 6 
 7 void GetNext(string p,int next[]){    
 8     int pLen = p.length();    
 9     next[0] = -1;    
10     int k = -1;    
11     int j = 0;    
12     while (j < pLen - 1){    
13        //p[k]表示前缀,p[j]表示后缀    
14         if (k == -1 || p[j] == p[k]){    
15             ++k;    
16             ++j;    
17             next[j] = k;    
18         }    
19         else k = next[k];    
20     }    
21 }    
22 
23 int KMP(string pattern,string str){//判断是否存在子串 
24     int i,j;
25     int plen=pattern.length();
26     int len=str.length();
27     for(i=0;i<len;){
28         for(j=0;j<plen;j++){
29             if(str[i+j]!=pattern[j])
30             break;
31         }
32         if(j==plen)
33         return 1; 
34         i+=j-next[j];
35     }
36     return 0;
37 }
38 
39 int main(){
40     string str1,str2;
41     cin>>str1;
42     cin>>str2;
43     if(str1.length()!=str2.length()||str1.length()==0||str2.length() ==0){
44         cout<<"false";
45     }else{
46         str1+=str1;
47         GetNext(str2,next);
48         if(KMP(str2,str1)){
49             cout<<"true";
50         }
51     }
52     return 0;
53 }

 




以上是关于两串旋转问题(KMP)的主要内容,如果未能解决你的问题,请参考以下文章

字符串旋转(str.find()---KMP)

处理屏幕旋转上的片段重复(带有示例代码)

使用 ActionBar 旋转 Android 的双片段

KMP字符串匹配算法详解

Butterknife 片段旋转给出 NullPointer

字符串KMP || HDU 1711 Number Sequence