KMP 個人理解總結

2021-10-04 14:48:10 字數 2147 閱讀 1271

這幾天複習kmp演算法,發現自己看別人的講解又看糊塗了,所以還是需要將別人的思想理解之後,自己再輸出一邊。

kmp的出現是為了優化樸素模式匹配演算法,那麼樸素模式匹配演算法是什麼?又存在什麼缺點呢?

樸素模式匹配演算法:複雜度o(n*m),就是將主串中與模式串長度相同的子串提取出來,挨個和模式串對比,當子串與模式串某個對應字元不匹配時,就立即放棄當前子串,檢索下乙個子串。

/* 字串下標始於0 */

int*****stringsearch

(string s, string p)

else

//不相等}if

(j == p_len)

//匹配成功

return i - j;

return-1

;}

這裡面就存在乙個問題,就是每次遇到不匹配時,主串和模式串都要回溯,即**中的i = i - j + 1j = 0。這樣是非常不划算的,因為你已經知道前面的字元是哪些了(你已經掃瞄過一遍了),它和模式串有沒有可能匹配你也是知道的,所以再回去重新掃一遍浪費時間。

於是就誕生了kmp演算法,它的優化思路是:不回溯主串,只回溯模式串。也就是說當主串和模式串不匹配的時候,我就把模式串的指標j指向模式串中可能和當前主串字元相匹配的位置,讓他們繼續比較。這個可能和主串字元匹配的位置 構成的新陣列就是next陣列。

例如,如圖1所示,當匹配到d時,發現匹配不上了,樸素模式匹配演算法會讓主串和模式串都回溯(子串和模式串都回到首字元處),再重新開始比較。

而這是沒必要的,因為你已經知道i前面的字元是abcdab,那麼模式串中可能和當前主串i字元' '相匹配的位置是c,因為主串abcdab中的最後兩個字元ab和模式串abcdab中的最開頭兩個字元ab匹配,那麼我直接讓模式串的指標j回到c的地方,讓c和' '比較就行。

next陣列存放的是回溯的下乙個需要比較的位置,即這個位置之前的字元都已經是匹配的了。

next[i]等於p[0]…p[i - 1]最長的相同真前字尾的長度。由於字串是從0開始的,所以這個長度所在位置就是 匹配字串 的下一位,也就是回溯的下乙個需要比較的位置。

/* p 為模式串,下標從 0 開始 */

void

getnext

(string p,

int next)

else

j = next[j];}

}

其中的關鍵部分在於next[i]=jj=next[j]

可以這樣理解:

#include

#include

using

namespace std;

/* p為模式串,下標從0開始 */

void

getnext

(string p,

int next)

else

j = next[j];}

}/* 在s中找到p第一次出現的位置 */

intkmp

(string s, string p,

int next)

else

j = next[j]

;//當前字元匹配失敗,進行跳轉}if

(j == p_len)

//匹配成功

return i - j;

return-1

;}intmain()

; cout <<

kmp(

"bbc abcdab abcdabcdabde"

,"abcdabd"

, next)

<< endl;

//15

return0;

}

KMP演算法個人理解總結

關鍵點 公共前字尾字串 1.首先按照bf比較後,出現的那個不匹配的字元往前找,比如圖中是ab。每次要取最長公共前字尾字串,比如圖中最長的是ab。2.然後,把最長字首移到最長字尾的位置,再從最長字尾開始比較。這是按照移動模式串 子串 的思維來的。實際上操作是這樣 每次開始比較的編號,等於最大公共前字尾...

KMP 演算法(個人理解)

相信大家看了 matrix67 的講解,一定已經知道了 kmp 演算法是怎麼回事,怎麼操作的,為什麼時間複雜度不高 這裡,我主要是分享我對 kmp 的理解 kmp 的精髓是什麼?這個東西,各自有個字的理解,很多人都覺得是避免了重複匹配,而我的理解是預處理 為什麼是預處理?你看看 kmp 的執行過程 ...

KMP演算法的個人理解

自學了一段時間,剛剛準備轉行做軟體開發,面試過程中被指出計算機基礎知識薄弱。因為是非科班出生,確實有些計算機方面的基礎沒有學過,也開始惡補這些方面的東西。最近在學習資料結構與演算法過程中,學到kmp演算法,甚是難解。看了阮一峰的網路日誌後才慢慢理解,但也發現其中的瑕疵,在此也順帶指出,至於對或不對,...