參考:
2016-08-22
前言:自己看《演算法導論》中關於kmp演算法的講解,文字描述+插圖+偽**,但最終還是雲裡霧裡。之後借助於上面提到的部落格才有所體會。感謝博主。
對於其最核心的部分---當模板字串中前面q個字元和源字串中的某個子串匹配時,如果繼續往下匹配,發現兩個字元並不相同,那該如何移動模板字串進行比較呢?
1. 最簡單的方法當然是,將模板字串向後移動一位,繼續從頭開始比較每乙個字元。很明顯,這樣做雖然可行,但是效率很差,因為你要把"搜尋位置"移到已經比較過的位置,重比一遍。
那麼kmp演算法的移動方法是什麼呢?
答案是:借助乙個next陣列(也稱為部分匹配表)來計算下次字串移動的位數應該是多少。
如下圖所示:
下面介紹部分匹配表是如何產生的:
"部分匹配值"就是"字首"和"字尾"的最長的共有元素的長度。以"abcdabd"為例,(這只是相對於模板字串而言,與源字串無關)
首先,要了解兩個概念:"字首"和"字尾"。 "字首"指除了最後乙個字元以外,乙個字串的全部頭部組合;"字尾"指除了第乙個字元以外,乙個字串的全部尾部組合。
例如:- "a"的字首和字尾都為空集,共有元素的長度為0; q=1
- "ab"的字首為[a],字尾為[b],共有元素的長度為0; q=2
- "abc"的字首為[a, ab],字尾為[bc, c],共有元素的長度0; q=3
- "abcd"的字首為[a, ab, abc],字尾為[bcd, cd, d],共有元素的長度為0; q=4
- "abcda"的字首為[a, ab, abc, abcd],字尾為[bcda, cda, da, a],共有元素為"a",長度為1; q=5
- "abcdab"的字首為[a, ab, abc, abcd, abcda],字尾為[bcdab, cdab, dab, ab, b],共有元素為"ab",長度為2; q=6
- "abcdabd"的字首為[a, ab, abc, abcd, abcda, abcdab],字尾為[bcdabd, cdabd, dabd, abd, bd, d],共有元素的長度為0。 q=7
最後,
模板字串移動的位數 = q - 部分匹配值。(其中q表示已經匹配的字元的個數。)
" 部分匹配"的實質是,有時候,字串頭部和尾部會有重複。比如,"abcdab"之中有兩個"ab",那麼它的"部分匹配值"就是2("ab"的長 度)。搜尋詞移動的時候,第乙個"ab"向後移動4位(字串長度(q) - 部分匹配值),就可以來到第二個"ab"的位置。
所以,通過避免一些不必要的比較,這樣就可以提高演算法效率,時間複雜度為o(m+n),而一般方法複雜度為o(m×n)。
演算法理解,到此就清楚了,實現**如下:
簡單匹配演算法的時間複雜度為o(m*n),kmp匹配演算法,可以證明它的時間複雜度為o(m+n).。
一.簡單匹配演算法
KMP演算法 字串快速匹配
kmp演算法的實現 最近學習了資料結構中乙個重要的內容 字串.涉及到乙個重要也是難理解的演算法 kmp演算法,即字串快速匹配模式串的演算法.在這裡寫一下心得體會,以便後來者參考.在開始之前,還是先講一講樸素的字串匹配演算法 暴力搜尋.先講幾個基本概念 所謂暴力搜尋,就是從主串和模式串開頭字元開始,乙...
sunday演算法研究 超越kmp的字串匹配
第一次聽到sunday演算法,是大餅餅說的。在他 並茂的解釋中,我發現這個演算法果然是乙個又容易理解,效率又強過kmp和bm的演算法。於是試著寫了乙個,果真是好東東,分享一下。轉一些概念先 sunday演算法是daniel m.sunday於1990年提出的一種比bm演算法搜尋速度更快的演算法。其核...
串 KMP模式匹配演算法理解筆記
記錄貼膜小哥對kmp模式匹配演算法的粗淺理解以及筆記 詳細學習可以參考這篇 kmp不錯的講解。由於樸素模式匹配演算法的低效o n m 所以有三位前輩研究出了o n m 的匹配演算法 kmp 樸素演算法的低效在於,匹配不成功時候,主串和子串都要進行回溯。kmp演算法的優越性在於,主串不用回溯,且子串重...