KMP代碼及思路解析


首先推薦這篇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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章