看过很多篇关于KMP的博文,老感觉总结的结论相互之间有出处,这里我把最终整理出来的结论分享一下。【其实私心想想有出处的地方也没有对错之分,只是看匹配发生在next生成的时候,还是匹配长字符串的时候】
第一部分:getNext
思想:
next[0] = -1;
p[0…k-1] =p[j-k…j-1]的最大的k(k<j), next[j] = k eg:abdabc next[5] = 2; 但是如果匹配不到(k=0)next[j] = 0,如果匹配到了但是结束字符也一样的话next[j] 仍要为0 eg:abcabc next[5] = 0,这些情况下如果又与首字符一样的话next[j]==-1;
完整代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
const int Max = 10;
using namespace std;
int next[Max];
bool equals(string s1, string s2){
bool flag = true;
for(int i = 0 ; i < s1.length() ; i++){
if( s1[i] != s2[i] ) flag = false;
}
return flag;
}
void getNext(string str2){
memset(next,0,sizeof(next));
int pos = 0;
next[pos] = -1;
pos++;
for( ; pos < str2.length() ; pos++){
int k = pos-1;
for( ; k > 0 ; k--){
if( equals( str2.substr(0,k),str2.substr(pos-k,k) ) )next[pos] = k;
}
//本身没有相匹配的字符,或者匹配到最后发现相同段同样应该将它归零
if(k==0 || str2[pos] == str2[k]) {
next[pos] = 0;
if(str2[pos] == str2[0]) next[pos] = -1;
}
}
}
int main(){
string str1;
string str2;
cin>>str1;
cin>>str2;
getNext(str2);
int match = 0;
for(int i = 0 ; i < str1.length() ; i++){
if( str1[i] == str2[match] ) match++;
else{
//cout<<"current fail_position::"<<i<<endl;
//next[pos] = -1;对str1的下一个字符继续匹配,但是str2从头
//next[pos] != -1;对str2的当前字符再次匹配,str2从避免重复的指定开始位置开始
if( next[match]==-1 ){
match = 0;
}else{
match = next[match];
i--;
}
}
if( match == str2.length() ) {
cout<<"end match"<<endl;
return 0;
}
}
return 0;
}