1. 程式人生 > >KMP演算法最詳細分析!!

KMP演算法最詳細分析!!

1.首先明確,next陣列存在的意義是什麼:

示例如下:

主串:  a b a b c a b c a c b a b

模式串: a b c a c

匹配過程如下:

第一次匹配:

這個時候,如果不用KMP,而是用BF,那麼我們的做法很明顯:

嘗試模式串的第一個字元和主串的第二個字元進行匹配。

很明顯,這是多餘的,這是肯定不成立的,而next陣列直接告訴我們,跳過這一步,直接如下

這就是next的作用,如果還不明顯,你再看上圖,模式串的第五位是c和主串相對位置的b不匹配,那麼按照BF演算法,我們需要

再用主串的第四位和模式串的第一位比較,但是,很舒服,next陣列告訴我們不用這樣,直接如下

以上就是next的作用,跳過無用的匹配。

2.思考,next為什麼可以這樣做呢?

首先,什麼是next陣列:

上述模式串的next陣列如下:

a b c a c

0 1 1 1 2

簡而言之,每個字母x對應的next陣列值是這樣的出來的:x前的子串和主串的前幾個字母相同,則只需要比較x和主串的第y個元素就好了,那麼這個y就是next[x的索引]的值。

下面引入求next陣列的演算法:

next儲存起始從1開始

void GetNext(string s,int next[])//s是模式串

{

    int i=1,j=0;next[1]=0;

    while(i<s.length()-1){

        if(j==0||s[i]==s[j]){

            i++;j++;

            next[i]=j;

        }

        else{

            j=next[j];//這一步很關鍵,他起到的作用就是剛才上面講到的配對失敗之後,直接跳到指定的位置

        }

    }

}

既然已經得到next陣列了,那麼實際操作就很簡單了,附上KMP程式碼:

int KMP(string s,string t,int pos)//引數分別是主串,模式串,求模式串在主串第pos個字元之後的位置

{

    int i=pos,j=1;

    while(i<s.length()&&j<t.length()){

        if(j==0||s.data[i]==t.data[j]){

            i++;j++;//均後移一位

        }

        else j=next[j];//找到適當的位置

    }

    if(j>t.length())return i-t.length();//匹配成功

    else return -1;

}