之前找了几篇KMP算法详解,还有视频。都不是很能搞明白代码怎么实现。然后看了胡凡的算法笔记,感觉非常的简单易懂,一遍看下去直接明白了~~在书中的445页。想清楚了解的可以下载电子档看相关内容~~~因为内容解析文字过多,这里只贴代码。
KMP算法实现代码如下:
#include<iostream>
using namespace std;
int Next[100] = {0};
void getnext(string substr);//获取子串的next数组
bool KMP(string str,string substr);//判断模式串中是否包含给定子串
int KMP_count(string str,string substr);//统计模式串中包含多少个给定子串
int KMP_pos(string str,string substr,int pos);//从指定位置找子串出现的位置
int main(){
string str = "abababab";
string substr = "abab";
bool issubstr = KMP(str,substr);
if(issubstr)
cout<<"是子串"<<endl;
else
cout<<"不是子串"<<endl;
int count = KMP_count(str,substr);//判断包含几个子串
cout<<"子串数量为:"<<count<<endl;
int pos = KMP_pos(str,substr,3);//判断包含几个子串
cout<<"出现位置为"<<pos<<endl;
return 0;
}
void getnext(string substr){//获取子串的next数组
int j=-1;
//next[i]中的i代表substr[0..i]最长相等前后缀的前缀最后一位的下标
Next[0] = -1;//初始化 j = next[0] = -1
for(int i=1;i<substr.length();i++){
while(j != -1 && substr[i] != substr[j+1])
{
j = Next[j];//反复令 j = Next[j]
}
if(substr[i] == substr[j+1])
j++;
Next[i] = j;
}
}
bool KMP(string str,string substr){//判断模式串中是否包含给定子串
int j=-1;
getnext(substr);
for(int i=0;i<str.length();i++){
while(j != -1 && str[i] != substr[j+1])
j = Next[j];
if(str[i] == substr[j+1])
j++;
if(j == substr.length()-1)
return true;
}
return false;
}
int KMP_count(string str,string substr)//统计模式串中包含多少个给定子串
{
int j = -1,cnt = 0;
getnext(substr);
for(int i=0;i<str.length();i++){
while(j != -1 && str[i] != substr[j+1])
j = Next[j];
if(str[i] == substr[j+1])
j++;
if(j == substr.length() - 1)
{
cnt += 1;
j = Next[j];//匹配时注意是j = Next[j],不能是j = -1,否则会漏解从而造成错误,并且增加无意义的工作
}
}
return cnt;
}
int KMP_pos(string str,string substr,int pos){
int j=-1;
getnext(substr);
for(int i=pos-1;i<str.length();i++){
while(j != -1 && str[i] != substr[j+1])
j = Next[j];
if(str[i] == substr[j+1])
j++;
if(j == substr.length()-1)
return i - substr.length() + 1;
}
return -1;
}
运行结果如下: