這裡
kmp演算法是一種改進的
字串匹配
演算法,由d.e.knuth與v.r.pratt和j.h.morris同時發現,故稱kmp演算法
字串匹配:從字串t中尋找字串p出現的位置(p遠小於t)。其中p稱為「模式」。
kmp演算法對模式串進行o(m)的預處理後只需對文字t掃瞄一次即可找到匹配,所以時間複雜度為o(n+m)。
先不管o(m)的預處理,直接看o(n)的掃瞄。
對於下圖的字串匹配:(圖1)
1 :i=0 , j=0 , 判斷t[i] != p[j],則 i++.
2 : i=1, j = 0 , t[i]==p[j] , 則i++,j++
3 : 依次判斷t[2...5] == p [1...4] , 此時i = 6, j = 5 . t[i] != p[j] . (圖2)
如果使用bf演算法, i 指標在此時匹配失敗後會回溯, 然後重新進行匹配 .
kmp演算法中則不對 i 指標進行回溯, 而是修改 j 指標. 此時執行操作 j = next[j] = 2 , 繼續進行匹配; 其中next陣列是通過o(m)的預處理求得的, 暫時不管
4:(圖3中, p2的 j 指標是圖2中的 j 指標)由於我們從t[1]開始匹配直到t[6]才出現匹配失敗的情況, 所以t[1...5]==p[0...4]. 很明顯圖中圈出的兩個串相等, 即 p[0 , 1] == t[1 , 2]
5:通過觀察我們又能發現, p[0 , 1] == p[3 , 4]; (這就是o(m)預處理出的next陣列中值的意義 , next[5] = 2 , 則p[0...2-1] == p[5-2...5-1])
同步驟4,由於直到t[6]才出現匹配失敗, 所以又p[3 , 4] == t[4 , 5] . 所以p[0 , 1] == t[4 , 5].
在對 j 指標進行 j = next[j] 操作後, p3 [0 , 1] 就對應著p2 [3 , 4]. 即p3[0 , 1] == t[4 , 5] . 所以kmp演算法才會直接將j 指標跳到2而不是0 , 省去了對前一部分的匹配 , 也保證了不會漏掉匹配
6:p[0...5] == t[4...9] , 匹配成功.
--------------
在對next的預處理中 , 如果找不到乙個像上面的p[2]一樣合適的位置 , 就只能從p[0]開始匹配 , 並且在當前的 i 位置不會找到匹配了 ,所以next = -1. 程式執行j = next[j] = -1後 , 在下一次迴圈中 判斷j==-1 就執行i++,j++. 通過這樣處理, 省去了 i 指標的回溯 , 降低了時間複雜度 . 因為這樣操作每次匹配無論成功還是失敗都會有 i++ , 所以時間複雜度是o(n)
c/c++ code:
int kmpmatch(char *s,char *p)
else //p[j]!=p[k]
k=next[k];}}
KMP演算法的簡單理解
對於串的匹配,較為簡單的有bf演算法,但這種方法的可用性卻較差。因為在每次不匹配的時候,主串 m位 和子串 n位 都會回溯,有一種最壞的情況就是,主串每前進一位,都在n次匹配後失敗然後回溯,如 主串 aaaaaaaaaaaaaaaaaaaaab 子串 aab 這樣會導致bf演算法的時間複雜度大大提公...
KMP演算法的理解
串的模式匹配演算法主要有兩種,一是簡單模式匹配,而是kmp演算法。簡單模式匹配演算法很容易理解,每一次從主串的第乙個位置起和模式串的第乙個字元開始比較,如果相等就按照順序一直比下去,如果不相等就把模式串和第二個位置開始繼續進行比較,最後若匹配成功則返回主串中與模式串匹配的第乙個字元的位置,雖然簡單易...
理解KMP演算法
由暴力匹配引入kmp演算法 問題 有乙個文字串s,和乙個模式串p,現在要查詢p在s中的位置。如果用暴力匹配的思路,並假設現在文字串s匹配到 i 位置,模式串p匹配到 j 位置,則有 示例 上面s,下面p 比如從a這裡開始匹配上了 一直這樣匹配下去 到這裡匹配不上了 就回滾回去重新開始 這種回滾的問題...