其實kmp演算法與bf演算法的區別就在於kmp演算法巧妙的消除了指標i的回溯問題,只需確定下次匹配j的位置即可,使得問題的複雜度由o(mn)下降到o(m+n)。
在kmp演算法中,為了確定在匹配不成功時,下次匹配時j的位置,引入了next陣列,next[j]的值表示p[0...j-1]中最長字尾的長度等於相同字串行的字首。
假設主串:s: 『s(1) s(2) s(3) ……s(n)』 ;
模式串 :p: 『p(1) p(2) p(3)…..p(m)』
繼續現在我們假設 主串第i個字元與模式串的第j(j<=m)個字元「失配」後,主串第i個字元與模式串的第k(k此時,s(i)≠p(j), 有
主串: s(1)…… s(i-j+1)…… s(i-1) s(i) ………….
|| (相配) || ≠(失配)
匹配串: p(1) ……. p(j-1) p(j)
由此,我們得到關係式
『p(1) p(2) p(3)…..p(j-1)』 = 』 s(i-j+1)……s(i-1)』
由於s(i)≠p(j),接下來s(i)將與p(k)繼續比較,則模式串中的前(k-1)個字元的子串必須滿足下列關係式,並且不可能存在 k』>k 滿足下列關係式:(k即:
主串: s(1)……s(i-k +1) s(i-k +2) ……s(i-1) s(i) ………….
|| (相配) || || ?(有待比較)
匹配串: p(1) p(2) …… p(k-1) p(k)
現在我們把前面總結的關係綜合一下
有:s(1)…s(i-j +1)… s(i-k +1) s(i-k +2) …… s(i-1) s(i) ……
|| (相配) || || || ≠(失配)
p(1) ……p(j-k+1) p(j-k+2) ….... p(j-1) p(j)
|| (相配) || || ?(有待比較)
p(1) p(2) ……. p(k-1) p(k)
由上,我們得到關係:
『p(1) p(2) p(3)…..p(k-1)』 = ' p(j-k+1) p(j-k+2) p(j-k+3)……p(j-1)』
這樣歸結到了求next函式。
下面是next函式方法:
1void getnext(char* t, int* next)
2 15
else
16
19 }
20 }
當乙個字串以0為起始下標時,next[i]可以描述為"不為自身的最大首尾重複子串長度"。
也就是說,從模式串t[0...i-1]的第乙個字元開始擷取一段長度為m(m < i-1)子串,再擷取模式串t[0...i-1]的最後m個字元作為子串,如果這兩個子串相等,則該串就是乙個首尾重複子串。我們的目的就是要找出這個最大的m值。
詳細例項見朱站立版《資料結構》例4-5。
KMP演算法總結
kmp題目重在理解next陣列的含義 next陣列的作用 next j 記錄模式串中第 j 個字元的最長公共字首長度 重要,這是它的意義所在 第二種理解方式,當模式串與主串失配時,跳回的位置。next len 即字串 0 結束標誌的next值 單個字串匹配時與週期有關 hdu 1711 模板題 33...
KMP演算法總結
kmp演算法是用來實現模式匹配的,其時間複雜度是o m n 具體原理見 其中有用到next陣列來計算子串中公共項的位數,簡單來說,就是子串遇到不匹配時,就查next資料來決定前進幾位 移動位數 已匹配的字元數 對應的部分匹配值 1 要不要減一看next陣列第一位是不是為1,個人覺得加一後是有好處的,...
KMP演算法總結
現在假設有兩個字串a bbc abcdab abcdabde,b abcdabd。現在要在a中找b。比較暴力的方法是直接搜尋 void gosearch 上述 最核心就是while迴圈,舉兩個例子說明其作用 還是選取b串作為說明。假設現在要求next 6 那麼當前的j next 5 1 next陣列...