KMP演算法學習

2021-07-22 06:17:22 字數 1913 閱讀 2243

簡單模式匹配最壞複雜度在:o(n*m)

kmp可以牛到在o(n+m)的時間數量級上完成串的模式匹配操作。

核心來了:

改進:每當一次匹配過程中出現字元比較不等時,不需要回溯i指標(主字串),而是利用已經得到的」部分匹配」的結果將模式向右」滑動」盡可能遠的一段距離,繼續進行比較。

所以核心在於,向右滑動多少距離怎麼計算。

終於搞得懂了,記錄一下。

設主串是s,模式串是p。

用i指標在s串中游動,j指標在p串中游動。不用考慮i,j是從0開始計數還是從1開始計數。任選乙個,這裡我選擇從1計數。

也即:s1s2s3….sn

p1p2p3….pm

上面我們說,核心在於失配時,模式串盡可能向右滑動遠的一段距離

這是感性的說法,用可量化的語言描述是:當s[i] != p[j]時,i指標不要回溯,而是想,s[i]和p[k]再比較,這樣只需要針對模式串進行研究

以下是數學推導:

失配時,已經部分匹配的是:p1p2…pj-1 = si-j+1si-j+2…si-1

注意下標。

假設此時應與模式中第k個進行比較,必須要滿足的條件是:

模式串中前k-1個字元的字串必須和s[i]前面k-1個字元匹配。

即:

p1p2...pk-1 = si-k+1si-k+2…si-1  (1)
此時讓s[i]與p[k]比較,所以部分匹配滿足:

pj-k+1pj-k+2…pj-1 = si-k+1si-k+2..si-1  (2)
這裡的j仍是當前未回溯的j的值。其實,在失配時:

p1p2...pj-1 = si-j+1...si-1,上面只是選取一部分與(1)可聯立方程。
所以由(1) (2)可以推導出:

p1p2…pk-1 = pj-k+1pj-k+2…pj-1(*)
也就得到了在失配時,如何僅僅根據模式串自身就能找到k值

的公式了。p[

1]=p

[j−k

+1]p

[2]=

p[j−

k+2]

p[3]

=p[j

−k+3

]...

p[k−

1]=p

[j−1

] 左邊序號是公升序,右邊也是公升序。因此,尋找的k值是:失配字元之前字首和字尾相等的最大長度+1

特別注意k的含義是:指向下乙個與文字串比較的在模式串中的位置,而字首和字尾相等是公共部分,長度+1後才是k的位置。

令next[j] = k,我們就得到了常用的函式:

next[j] = 0, 當j = 1時

next[j] = max

next[j] = 1,其他情況

再次說明:next[j] 表示的是當模式中第j個字元與主串中相應的字元失配時,在模式中需要重新與主串中該字串進行比較的字元的位置。

所以是基於j指標進行k的尋找,j是失配時候的值。

有了next[j]函式,那麼匹配過程就可以描述為:

假設以指標i和j分別致使主串和模式中正待比較的字元,令i的初值為1.

若在匹配過程中,si = pj,則i++,j++

否則失配,i保持不變,j回退到next[j],即: j = next[j].再比較si和pj

若回退到j為0,則表示第乙個字元就失配,此時需要主串的下乙個位置開始於模式重新開始匹配。

以後再補**。

KMP演算法學習

先貼上一點 等腦子清醒點再好好理解 求next陣列 public static int getnext string pattern else else return next public static int search string src,string pattern,int nextva...

KMP演算法學習

一 什麼是kmp演算法 knuth morris pratt 字串查詢演算法 常簡稱為 kmp演算法 是在乙個 主文字字串 s內查詢乙個 詞 w的出現,通過觀察發現,在不匹配 發生的時候這個詞自身包含足夠的資訊來確定下乙個匹配將在 開始 以此避免對以前匹配過的字元重新檢查。在原串中匹配模式串 二 k...

KMP演算法學習

1.kmp演算法簡介 2.樸素的匹配演算法 在介紹kmp演算法之前我們來看看那樸素的匹配演算法。定義 我們是在主串中搜尋模式串。如下圖當主串在e的位置與模式串發生失配時 e前面的都是匹配的 樸素的匹配演算法做的是,將模式串後移一位在去匹。我們可以思考這樣做是否有意義,因為模式串c前面是與主串匹配的,...