首先推薦這篇KMP思想的介紹:字符串匹配的KMP算法
KMP代碼的關鍵是:
1、得到搜索串每個字符的匹配值
2、當字符匹配失敗時的轉移
(搜索串指搜索目標串。)
1:
第一個循環:遍歷每個字符,表示搜索的是 該字符及之前所有字符組成的串。
第二個循環:遍歷所有長度的子串。
第三個循環:比較子串是否相同。
搜索的目標是:所有相同的子串中最長字串的長度。所以維護一個maxl變量。
(在此“子串”指前綴和後綴。)
(代碼中未清零model數組。)
2:
匹配失敗時的轉移就很簡單了。
若當前字符匹配失敗,前一字符的model值就是前面已匹配串的前綴與後綴相同的個數,直接令搜索串的偏移等於該數值就行。(代碼不同由於數組腳標可能會有+-1差別。)
void inis(string t, int* model){
//初始化得到搜索串的模式
//第一個循環 i爲字符串尾
for(int i=1; i<=t.size(); i++){
//第二個循環 k爲字串長度
for(int k=1; k<i; k++){
//cout<<"k:"<<k<<endl;
int maxl = 0;//最長匹配子串的長
bool ok = true;
//第三個循環 h爲子串比較的位
for(int h=0; h<k; h++){
//cout<<"h:"<<h<<"--"<<t[h]<<" "<<t[i-k+h]<<endl;
if(t[h] == t[i-k+h]){
maxl++;
}else{
ok = false;
break;
}
// cout<<h<<"-"<<len-k+h<<endl;
}
if(ok && maxl>model[i-1]){
model[i-1] = maxl;
}
}
}
}
int sf(string s, string t, int* model, int off){
//從偏移off處開始搜索 返回目標串首字符從0開始的索引
int slen = s.size();
int tlen = t.size();
int i=off, k=0;
for( ; i<slen; i++){
//cout<<"i:"<<i<<endl;
//cout<<s[i]<<" "<<t[k]<<endl;
if(s[i] == t[k]){
//cout<<"k++ "<<k<<endl;
k++;
}else{
//狀態轉移
if(k != 0){
k = model[k-1];
i--;
}
}
if(k == tlen){
return i - k + 1;//首
//return i;//尾字母
}
}
return -1;
}