1. 程式人生 > >KMP算法講解

KMP算法講解

數組 gpo 重復 錯誤 第一步 復雜 pic 字符串匹配 沒有

轉載自傅少博客

那麽首先我們知道,kmp算法是一種字符串匹配算法,那麽我們來看一個例子。

比方說,現在我有兩段像這樣子的字符串:

技術分享圖片

分別是T和P,很明顯,P比T的長度要短很多,我們要做的事情呢,就是找找T中有沒有和P相同的一段。

如果按照最簡單的辦法來做匹配的話,我們一般是一個一個字母的來做。

像這樣:

技術分享圖片

很顯然,圖中前面3位都是能匹配的,而第四位卻不能匹配,怎麽辦?

這樣:

技術分享圖片

我們就會將整個P字符串向右移動一格,又重新開始,從T中b處與P中第一個a處開始匹配。

如此往復,顯然這樣是很慢的,因為我們來考慮考慮這樣一種極端的情況:

技術分享圖片

像這樣,顯然一位一位匹配是會做許多重復的操作的。

那麽現在我們來考慮使用一下kmp算法。

怎麽做呢?

首先我們需要處理一個叫做前綴表(prefix table)的東西(有些博客說是next[]數組,其實是一樣的)。

什麽是前綴呢?比如說,P字符串為a b a b c,那麽P的前綴即為a,a b,a b a,a b a b和a b a b c共五個。

技術分享圖片

所以,做kmp算法時,我們先要把我們要搜索的那一個字符串的所有前綴都寫出來。這是第一步。

好,那麽第二步,我們就要將之前處理出的所有前綴當做不同的幾個字符串。

然後,我們對每個這樣的前綴字符串處理一下,處理出一個叫做最長公共前後綴的東西。

最長公共前後綴是比原來字符串要短的前綴與後綴最長公共部分的長度,這是什麽意思呢?聽起來特別拗口。

技術分享圖片

比方說,我們來看看第四個前綴字符串。很顯然,它的最長前綴是a b a,最長後綴是b a b(忽略本身)。

明顯這兩者是不同的,所以長度取3時是不行的。那麽我們取2,此時前綴是a b,後綴是a b,二者相等。

這時我們就將2稱作字符串a b a b的最長公共前後綴。

技術分享圖片

如圖,我們處理出了前綴表中的所有最長公共前後綴。

技術分享圖片

而在KMP算法中,前綴表裏長度等於本身的那個並不需要處理,舍去,而需要在最上面添加一個-1。

(等下模擬時,其作用就顯而易見了)。

現在我們已經處理好了prefix table,即-1 0 0 1 2 0。

接下來,進行第三步,將prefix table與P字符串對應,並標好下標index

1、技術分享圖片 2、技術分享圖片

如圖,上層是index,下層是prefix。

然後,我們模擬一下KMP算法是如何利用處理好的前綴表來計算運行的。

技術分享圖片

如圖,前面3位,我們還是如之前一樣完美匹配,但是到了第四位,就匹配不了了,怎麽辦呢?

不同以往,我們不再是往右移一格,而是跳到這一位對應的prefix所指的index處,!@#$%^&*...好繞啊啊啊!

上圖吧:

技術分享圖片

此時待匹配的位置的index,是不是就是之前發生錯誤的那個第四位所對應的prefix呢?

這樣,我們便可以直接從P中第二位開始重新匹配啦!!!

p.s.忘了說了,如果prefix是-1,那麽就直接向右移一格。

真是神奇訥、

不知道讀者是否還記得之前提出的極端情況。

技術分享圖片

如果用KMP算法,處理好前綴表後,是不是這樣:

技術分享圖片

所以 當匹配到a b時,那麽就直接會跳到index為3的a處,而跳過匹配前面3個a,時間復雜度大大降低↓↓↓。

KMP算法講解