KMP演算法原理

2021-08-13 00:57:03 字數 1593 閱讀 7553

字串匹配是最電腦科學的基本研究問題之一,在文件檢索、生物資訊等領域有著舉足輕重的地位。簡單來說字串匹配問題就是:如何確定某字串是否包含另一字串。暴力搜尋演算法(brute force, bf)是最容易想到和實現的,但是它高達o(n^2)時間複雜度難以滿足許多場景。kmp演算法是一種改進的字串匹配演算法,由d.e.knuth,j.h.morris和v.r.pratt同時發現。kmp演算法的特點就是利用了匹配失敗後的資訊,達到了減少模式串和主串匹配次數的目的,是一種廣泛應用的高效匹配演算法。

假定待匹配主串為t,模式串(pattern)為p。例如:

在講kmp之前我們首先來看一下暴力搜尋演算法(brute force, bf)是怎樣執行的。

首先是第一趟匹配,從t[0]和p[0]開始:

照此方法依次匹配下去,直到匹配成功或者到最後乙個字串匹配失敗返回。顯然暴力搜尋的複雜度為o(n^2),尤其是當主串為「aaaaaaaaaaaaaaab」,模式串為「aaaab」這類形式,匹配次數達到最大。

那麼怎樣才能改進暴力搜尋演算法呢?我們注意到,暴力搜尋過程的每趟匹配失敗後就開始下一趟匹配,並且每次匹配都是從頭開始重新匹配,如果我們能夠利用每次匹配失敗的資訊,就能夠大大減少重複勞動。這就是kmp方法的基本思想。

首先要引入字首表(prefix table)的概念:

對於模式串,它的字首就是從第乙個字元開始的某個字串,而字首表就由這些字串匯出。例如模式串p,它的字首分別是:

我們不考慮字首是模式串自身的情況,即將最後一行刪去。

下一步就是找出每個字首的最長公共前字尾的長度,比如字首「aba」的最長公共前字尾為

「a」,長度為1;字首「abab」的最長公共前字尾為「ab」,長度為2。

我們得到了字首序列:-1,0,0,1,2,然後將字首表對應模式串寫出來,就得到了字首表:

再一次開始匹配演算法。與暴力搜尋一樣,我們先從t[0],p[0]開始。不同的是模式串標註了字首表資訊(紅色)和下標資訊(藍色):

第一趟匹配:

匹配到第四個字元時發現a!=b,這時不像暴力匹配那樣直接進行下一趟匹配,而是檢視字首表,找到匹配失敗處的數字:

1,則下次匹配就從模式串下標

1的字元開始:

發現第乙個字元a!=b,檢視字首表,發現對應的是

0,則下次匹配從模式串下標為

0的字元開始:

(可以看出,從第一趟匹配到第二趟匹配,直接跳過了三個字元(綠色),比暴力搜尋的優勢就在這裡體現)

失敗處字首表對應的是

0,下趟匹配從模式串下標為

0的字元開始:

失敗處字首表對應的是

-1,下趟匹配從模式串下標為

-1的字元開始(模式串-1位置就是第乙個字元前的假定位置,匹配時直接從下標為0處開始即可):

失敗處字首表對應的是

2,下趟匹配從模式串下標為

2的字元開始......

繼續匹配直到搜尋到最後,退出kmp演算法。

KMP演算法原理

對於給定的字串strings和sub s,判斷strings中是否包含sub s,並返回出現位置,暴力演算法匹配字串過程 把strings 0 跟sub s 0 匹配,如果相同則匹配下乙個字元,出現不匹配的字元時我們會丟棄前面的匹配資訊,然後把strings 1 跟sub s 1 匹配,迴圈進行,直...

KMP演算法原理解析

這種演算法不太容易理解,網上有很多解釋,但讀起來都很費勁。直到讀到jake boxer的文章,我才真正理解這種演算法。下面,我用自己的語言,試圖寫一篇比較好懂的kmp演算法解釋。首先,字串 bbc abcdab abcdabcdabde 的第乙個字元與搜尋詞 abcdabd 的第乙個字元,進行比較。...

KMP字元匹配演算法原理

掘金位址鏈結 簡介 kmp演算法是一種改進的字元匹配演算法。由d.e.knuth,j.h.morris和v.r.pratt提出的,因此人們稱它為克努特 莫里斯 普拉特操作 簡稱kmp演算法 它的核心思想是,通過乙個next陣列,在匹配失敗後,減少字元移動的距離,達到快速匹配的目的。要想徹底理解kmp...