由暴力匹配引入kmp演算法 ---->問題:有乙個文字串s,和乙個模式串p,現在要查詢p在s中的位置。
如果用暴力匹配的思路,並假設現在文字串s匹配到 i 位置,模式串p匹配到 j 位置,則有:
示例:(上面s, 下面p)
比如從a這裡開始匹配上了:
一直這樣匹配下去:
到這裡匹配不上了:
就回滾回去重新開始:
這種回滾的問題在於:
在之前第4步匹配中,我們已經得知s[5] = p[1] = b,而p[0] = a,即p[1] != p[0],故s[5]必定不等於p[0],所以回溯過去必然會導致失配。
就是說,圖上s中紅框b我們之前就知道不等於下面這個紅框a了,回溯回去也沒用。
那有沒有一種演算法,讓i 不往回退,只需要移動j 即可呢?
yes===> kmp演算法,它利用之前已經部分匹配這個有效資訊,保持i 不回溯,通過修改j 的位置,讓模式串盡量地移動到有效的位置。
knuth-morris-pratt 字串查詢演算法,簡稱為 「kmp 演算法」,常用於在乙個文字串 s 內查詢乙個模式串 p 的出現位置,這個演算法由 donald knuth、vaughan pratt、james h. morris 三人於 1977 年聯合發表,故取這三人的姓氏命名此演算法。
下面先直接給出 kmp 的演算法流程(後續會詳述):
假設現在文字串s匹配到 i 位置,模式串p匹配到 j 位置:
示例:接著看上面的例子,到這裡發現匹配不到:
完整的例子:
如果給定文字串「bbc abcdab abcdabcdabde」,和模式串「abcdabd」,現在要拿模式串去跟文字串匹配。
移動位數 = 已匹配的字元數 - 對應的部分匹配值
==> 最大長度
表 / next陣列
原模式串子串對應的各個字首字尾的公共元素的最大長度表/next 陣列為:
我們看下上表是如何構造的:
最大長度值(也稱"部分匹配值")就是"字首"和"字尾"的最長的共有元素的長度。以"abcdabd"為例,
- "a"的字首和字尾都為空集,共有元素的長度為0;再copy一遍上面的演算法流程:- "ab"的字首為[a],字尾為[b],共有元素的長度為0;
- "abc"的字首為[a, ab],字尾為[bc, c],共有元素的長度0;
- "abcd"的字首為[a, ab, abc],字尾為[bcd, cd, d],共有元素的長度為0;
- "abcda"的字首為[a, ab, abc, abcd],字尾為[bcda, cda, da, a],共有元素為"a",長度為1;
- "abcdab"的字首為[a, ab, abc, abcd, abcda],字尾為[bcdab, cdab, dab, ab, b],共有元素為"ab",長度為2;
- "abcdabd"的字首為[a, ab, abc, abcd, abcda, abcdab],字尾為[bcdabd, cdabd, dabd, abd, bd, d],共有元素的長度為0。
示例匹配過程如下:
1. 因為模式串中的字元a跟文字串中的字元b、b、c、空格一開始就不匹配,直接將模式串不斷的右移一位即可,直到模式串中的字元a跟文字串的第5個字元a匹配成功:
2. 繼續往後匹配,當模式串最後乙個字元d跟文字串匹配時失配,模式串需要向右移動。但向右移動多少位呢?因為此時已經匹配的字元數為6個(abcdab),然後根據《最大長度表》可得失配字元d的上一位字元b對應的長度值為2,所以根據之前的結論,可知需要向右移動6 - 2 = 4 位。
3. 模式串向右移動4位後,發現c處再度失配,因為此時已經匹配了2個字元(ab),且上一位字元b對應的最大長度值為0,所以向右移動:2 - 0 =2 位。
4. a與空格失配,向右移動1 位。
6. 經歷第5步後(匹配cdabd的部分),發現匹配成功,過程結束。
通過上述匹配過程可以看出,問題的關鍵就是尋找模式串中最大長度的相同字首和字尾,基於此匹配。
參考 1
參考 2
參考 3
參考 4
理解KMP演算法(引用)
理解kmp演算法 引用 通用性的kmp演算法 void getnext st t,int next 由子串t求出next值 else k next k 滑動過程中如果出現不相等則認為以k個字元相等進行下一次滑動 kmpindex st s,st t,int pos maxstrlen為一常量,用來定...
KMP 演算法(個人理解)
相信大家看了 matrix67 的講解,一定已經知道了 kmp 演算法是怎麼回事,怎麼操作的,為什麼時間複雜度不高 這裡,我主要是分享我對 kmp 的理解 kmp 的精髓是什麼?這個東西,各自有個字的理解,很多人都覺得是避免了重複匹配,而我的理解是預處理 為什麼是預處理?你看看 kmp 的執行過程 ...
KMP演算法理解
kmp演算法的理解著實花了不少時間,幸好網上前輩的部落格寫得都相當好,結合幾篇部落格仔細想想還是可以理解的,這裡僅做一下整理。kmp演算法概念理解看這篇部落格就夠了字串匹配的kmp演算法by阮一峰 主要的邏輯那篇部落格都有講,求出next陣列,進行簡單的加減即可完成匹配。至於求解next陣列,則是k...