kmp演算法的關鍵是利用匹配失敗後的資訊,儘量減少模式串與主串的匹配次數以達到快速匹配的目的。
給定兩個字串t和w,長度分別為m和n,判斷w是否在t中出現,如果出現則返回出現的位置。常規方法是遍歷t的每乙個位置,然後從該位置開始和w進行匹配,但是這種方法的複雜度是o(mn)。kmp演算法通過乙個o(n)的預處理,使匹配的複雜度降為o(m+n)。
比如我們要在 字串t=「abcdabcdabde」中查詢 字串w="abcdabd"出現的位置
很明顯可以看出前6位都是匹配的,然而第7位不匹配,一般的做法就是從t[i](i從1到9)開始和w開始迴圈比較。直到i=4,也就是圖2,比較成功返回下標4。
這樣比較無異效率很低,然而我們發現在字串」abcdab」之中有兩個」ab」,第一次比較失敗之後,又迴圈比較了四次,把w字串從第乙個」ab」的位置移動到了第二個」ab」處(顯然這四次比較毫無意義)。kmp演算法就是要去掉這些無意義的比較。
「字首」指除了最後乙個字元以外,乙個字串的全部頭部組合;「部分匹配值」就是「字首」和」字尾」的最長的共有元素的長度。以w字串」abcdabd」為例:「字尾」指除了第乙個字元以外,乙個字串的全部尾部組合。
"a"的字首和字尾都為空集,共有元素的長度為0;
"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。
從上面我們就得出了字串w的部分匹配表:
我們把部分匹配表存放在乙個next陣列中,那部分匹配值究竟怎麼用呢? 我們可以根據部分匹配值計算出向後移動的位數,避免了一位位的比較:
移動位數 = 已匹配的字元數 - 對應的部分匹配值以圖1中為例:
前6位已經匹配(已匹配的字元數 =6); next[5] = 2 (對應的部分匹配值 = 2); 我們可以得出移動位數為 6-2=4位。
可以看出next陣列的作用,就是在我們匹配失敗的時候,確定我們子串需要往後移動的距離,而避免我們的主串指標進行回退。這樣可以保證主串在只遍歷一遍的情況下找到子串。
資料結構學習筆記之KMP模式匹配
kmp模式匹配演算法目的在於省去一般匹配中大量重複性的操作 每當匹配過程 現字元不同時不需回溯 i 指標,利用已的得到的部分匹配結果將模式串右移繼續匹配 以提高匹配效率,其中表示模式串前字尾特點的 next 陣列是此演算法的關鍵 include include include 前字尾資訊陣列 voi...
資料結構學習筆記
資料結構概述 定義我們如何把現實中大量而複雜的問題以特定的資料型別和特定的儲存結構 儲存到主儲存器 記憶體 中,以及在此基礎上為實現某個功能 比如查詢摸個 元素,刪除某個元素,對所有元素進行排序 而執行的相應操作,這個相應 的操作也叫演算法 資料結構 個體 個體的關係 演算法 對儲存資料的操作 演算...
資料結構學習筆記
資料結構學習筆記 程式 資料結構 演算法 資料結構 資料 結構 結構的本質是關係 資料之間的關係從不通風層面上分為邏輯關係和物理關係 演算法的設計要依據資料的邏輯關係 演算法的實現要依據資料的物理關係 物理關係是邏輯關係的基礎和載體 演算法實現時需要先依據問題抽象出資料模型,即初步確定待處理資料的邏...