通俗易懂的KMP演算法詳解(嚴蔚敏版C語言)

2021-08-09 17:40:05 字數 1765 閱讀 5585

最近,需要複習kmp演算法的next陣列,然後回頭看半年多後的我回頭看半年多前自己綜合別人內容寫的介紹。     沒錯,自己也看不懂。然後,自己再根據自己的理解寫了一下理解透徹的筆記,方便理解記憶,當然,以前的**解釋部分可以參考,筆記演算法思維和演算法的實現有一定的出入。望君諒解。(2018.9.30)

這是一條時間分割線

從剛接觸演算法,感覺是跟不上的一片片片段,再往後自己看書理解,片段更是碎成一點點亂碼。在下愚鈍,在查詢多種部落格,結合書上(嚴蔚敏的資料結構)解釋和**,詢問教師,後終於開竅。在此處引用了阮先生的部分思想,來通俗的講解一下kmp演算法。

解讀kmp之前,我們先來理解一下kmp演算法存在的理由。對於模式匹配,目前所學的最簡單的是bf演算法,即偏向於「暴力」匹配的方法。另外一種就是較為複雜kmp演算法了。而倆者的區別在於:bf演算法是時間複雜度相對高的,kmp則可以理解為用空間換時間。

bf演算法:        逐個匹配主串字元,然後模式串j值回溯到1重新匹配。

kmp演算法:       kmp只需要將j值模式串中j的位置回溯到next[j]位,而免除了前面不需要的匹配,以此來換取時間。

相比乙個乙個比較,同學們肯定會更加想詢問為什麼不直接從模式串第乙個字元和主串相同字元的位置比較即:       

而kmp則在此基礎上更加的簡便了。

接下來,我們來用有邏輯的語言來了解kmp演算法。而後,再解釋如何用**實現該演算法。

首先,我們從**的實現效果來看,主串與模式串每次歷往kmp演算法,模式串中移動至k位與失配的(主串)的i位對其,而不需要像bf演算法一樣,一次次回溯從頭開始。

那麼,問題來了。k為何物?

在此之前,我們來介紹一下最長字首和最長字尾,和部分匹配。

移動位數 =  已匹配值   -    部分匹配值     (其實就是直接從最長字首直接跳到與他相等的最長字尾那裡開始往後匹配)

上面都可以不用看

效果大概是這樣子:

以模式串abcdabd,文字串bbcabcdababcdabcdabde為例子展示最大公共元素長度(最長字首和他相等的最長字尾)。

再來一遍:移動位數 =  已匹配值   -    最大公共元素長度

關鍵是計算next陣列的值。

計算next陣列的值,偽**如下:

void get_next(sstring t, int next)else j=next[j];            //從模式串的第j位開始和後面匹配,就是直接從最長字首直接跳到與他相等的最長字尾那裡

通俗易懂的KMP演算法詳解

1.bf演算法 首先,簡單介紹bf 簡單的模式匹配法 假設主串為 abcbcglx 長度為m,模式串為 bcgl 長度為n。通常先從主串的下標0開始與子串的下標0開始匹配,如果匹配失敗,則從主串的第二個元素開始與子串的第乙個元素進行匹配。例如 第一次匹配 剛開始先用主串下標0 a 與子串下標0 a ...

通俗易懂的KMP演算法詳解

有些演算法,適合從它產生的動機,如何設計與解決問題這樣正向地去介紹。但kmp演算法真的不適合這樣去學。最好的辦法是先搞清楚它所用的資料結構是什麼,再搞清楚怎麼用,最後為什麼的問題就會有恍然大悟的感覺。我試著從這個思路再介紹一下。大家只需要記住一點,pmt是什麼東西。然後自己臨時推這個演算法也是能推出...

通俗易懂的EM演算法

假設現在有兩枚硬幣1和2,隨機拋擲後正面朝上概率分別為p1,p2。為了估計這兩個概率,做實驗,每次取一枚硬幣,連擲5下,記錄下結果,如下 硬幣結果統計1 正正反正反 3正 2反 2反反正正反 2正 3反 1正反反反反 1正 4反 2正反反正正 3正 2反 1反正正反反 2正 3反 可以很容易地估計出...