KMP演算法學習筆記

2021-08-26 20:48:00 字數 2028 閱讀 9488

kmp演算法的關鍵是主串不回溯。

每當主串和模式串匹配,i、j各自前進一格。這個和暴力匹配是一樣的。

出現不匹配的時候,因為不讓主串回溯了,代之以右滑模式串到乙個指定的位置。陣列next表示模式串的某一位置出現不匹配時,應該右滑到哪個位置。

next中取-1表示即使退回到第乙個值也無法匹配。所以,這時候也應該各自前進一格。

這樣一來,由於主串不回溯,對於長為m的主串來說,至少匹配了m次。

每次右滑,額外帶來一次匹配,但右滑的距離無法超過總距離。所以至多匹配了2m次。

也就是說,時間複雜度為o(m)。

讓我們手動跑一下……

大概就是這麼個原理。

**如下:

//kmp演算法

int kmp(string s1,string s2)

else

}if (j==s2.size())

else

}

next的求法:如果連第乙個值都無法與主串匹配,那顯然應該用模式串的第乙個值和主串的下乙個位置比較。令next[0]=-1。

next的其他值按以下步驟遞推而來:

若模式串s中下標為j的元素對應的next[j]為k,且s[j]=s[k],那麼令next[j+1]=k+1。(這是因為,next[j]=k意味著s最開頭0~k-1的元素與位於j前面的j-k~j-1元素一一相等,所以可以從k開始比較。如果s[j]=s[k],意味著位於0~k的元素與位於j-k~j的元素相等,也就是next[j+1]=k+1)

若s[j]不等於s[k],令k=next[k]。(如果j-k~j-1無法與最前面的k+1個元素匹配,也就是說我們沒辦法找到最長的這個串了。但是我們可以找到次長的。k肯定比j小,所以next[k]已經計算出來了。這裡一邊計算後面的結果一邊利用前面的結果。)

其實這些就夠了,不過它還能更快。如果不僅僅是s[j]==s[k],而且連s[j+1]==s[k+1]也成立的話……那麼s[j+1]不匹配的時候就沒必要跳到s[k+1]去了。反正s[k+1]肯定也不匹配,那我們可以直接跳到next[k+1]去。不過這只是有可能減少右滑模式串的次數,總的匹配次數依然是m~2m,時間複雜度也沒有變化。

手動跑一下的話比較直觀吧。就是省略了比較前兩個a。

**如下:

//取得模式串的next

void getnext(string s2, int

next)

else

}else}}

最後測試一下。

Kmp演算法學習筆記

kmp演算法我認為難點在next陣列的建立。看kmp前我仔細看了下傳統的匹配模式,為 首元素存放串的長度 int index sstring s,sstring t else i i j 2 if j t 0 return i t 0 else return 0 我認為想深刻理解好kmp演算法要和傳...

KMP演算法學習筆記

kmp是一種字串匹配演算法,網上有許多的講解和介紹,都非常清楚明白,這裡只說明一點next i 表示 1,i 1 位中的最長公共字首字尾,因此在遇到字元不匹配時,直接將字串右移j next j 位即可。不多說了,直接上習題 poj 3461 oulipo kmp演算法裸題,直接上模板 code in...

KMP演算法學習筆記

前幾天學習了關於字串處理的kmp演算法,剛學的時候沒怎麼懂,通過今天的練題,終於把kmp掌握了。kmp演算法利用了字串的一些特殊性質,通過字首陣列,將單個字串的匹配問題由o m n 優化到了o m n 這裡,我存幾段關鍵性 首先是get next 函式 void get next 然後是kmp vo...