kmp演算法的next陣列解析

2021-10-23 19:09:24 字數 2572 閱讀 8598

昨天天殺的 做了個字串匹配的題,於是天殺的 重新學習 kmp演算法(實際上第一次學的時候就沒搞懂 )。

首先搞清楚幾個概念:①什麼是字串匹配?比如給定字串"aabcaa",想要知道"abca"是否存在於該字串中,這個過程就是字串匹配。類似於string.indexof()。②什麼是kmp演算法?如果暴力破解,「abca」在匹配的過程中,先會匹配a,然後是b,如不同,就將"aabcaa"的指標向後移一位,再重新匹配。kmp使用next陣列,將重新匹配的過程減少,使得效率大大提公升。next陣列只與「abca」有關。

給定乙個非空的字串,判斷它是否可以由它的乙個子串重複多次構成。給定的字串只含有小寫英文本母,並且長度不超過10000。

示例 1:

輸入: 「abab」

輸出: true

解釋: 可由子字串 「ab」 重複兩次構成。 示例 2:

輸入: 「aba」

輸出: false 示例 3:

輸入: 「abcabcabcabc」

輸出: true

解釋: 可由子字串 「abc」 重複四次構成。 (或者子字串 「abcabc」 重複兩次構成。)

先放**:

class

solution

private

intkmp

(string s1, string s2,

int p)}if

(j ==-1

|| s[i]

== t[j]

)else}if

(j == n2)

return-1

;}private

int[

]getnext

(char

t)else

}return next;

}}

最關鍵的還是next陣列,次關鍵的是next陣列的應用。

next陣列的值是最長公共前字尾,在第 j 的位置(j 是長度),有k個字元(即字首)與後k個字元(即字尾)相同。

比如下圖 next[6] = 2 是因為前6個字元中的字首(前兩個"ab***x" )與字尾(後兩個 「***xab」 )相同。

測試一下理解:上圖中,不看已給結果,算一下next[8]是多少?

next陣列如何生成?

怎麼編碼呢?

next陣列的計算,以這張圖輔以理解,想象出乙個雙指標 j 和 k ,j 是第 j 個字元,用在t[j] 和 next[++j] (t陣列宣告在**),表示著當前正在比較的字元。k 是前字尾相同字元的個數,k 總是小於 j 的。每次 t [ k ] 與 t [ j ] 進行比較時,如果相同,那就讓 next [ ++j ] = ++k (因為next是長度為下標所以要+1) 。如果不相同,就讓 k = next[k] ,這個的含義在**中寫了,它的目的是減少重複比較,直接得出前字尾有多少個是相同的。

那這個next[0] = -1 的含義呢?其實他是不是-1根本無所謂,只要是負數就行,但不能是非負數因為會和next陣列的其他項重複。-1就是乙個標誌,他標誌著在 j 這個位置的所有前面的字元都沒有前字尾,也標誌著第0位與第 j 位不相等。

為什麼設定這個標誌位?先看為什麼 k 會等於-1,k會等於-1就是上一次 k = 0 ,這又是因為上一次第 j 位與第 0 位不相等,既然已經不相等了,那就需要讓 j++,讓next[j] = 0,讓 k = 0。設定了這個標誌位,就是設定了迴圈終止符,迴圈是k = next[k];所產生的迴圈。如果不設定這個標誌位next[0],就不能確定這次是比較還是讓 j++。

用上圖給出的字串在腦海中測試一下,看看自己理解的k = next[k];有沒有問題,如果有問題,你會在next[8]處寫上0(我之前就是 )

現在有主串s:ababcabcacbab,模式串t:abcac。i從0開始,j也從0開始。

根據上述方法可以知道,t的中每個字元對應的失效函式值為:

(將表中公共前字尾最長長度全部右移一位,第乙個值賦為-1)

第一次匹配中,i從0開始,j從0開始。當i=2,j=2時匹配失敗,此時i不動,next[j]=next[2]=0,接下來模式串t要相對於主串s向右移動j - next [j] = 2 位,j回溯到0。

KMP演算法中next陣列解析

接上篇 next 陣列 主要記錄 子串 的 每乙個字首 按順序 的 最長匹配真前字尾 的長度。這裡講一下 求解原理。陣列從零開始,第乙個數 1 代表不存在 有的以 0 為起點代表空,這不矛盾,全加1 即為此格式 此陣列是一點點增長的,下乙個資料依賴之前的資料。舉例子來描述原理 當新的最後乙個字母過來...

KMP演算法 next陣列

通過上文完全可以對kmp演算法的原理有個清晰的了解,那麼下一步就是程式設計實現了,其中最重要的就是如何根據待匹配的模版字串求出對應每一位的最大相同前字尾的長度。我先給出我的 1 void makenext const char p,int next 214 next q k 15 16 現在我著重講...

KMP演算法 NEXT陣列

kmp和next陣列基本上是一起用的,有了next陣列,才有kmp演算法,講道理來說這兩個都是基於最大前字尾和,也就是說需要用到kmp的時候必須先把next陣列先求出來,next陣列就是由所匹配的word的每個子串的前字尾和最大匹配得到的,說實話next陣列的演算法給優化得已經很無解了,以至於至今我...