模式匹配 KMP演算法

2021-08-17 06:43:50 字數 2405 閱讀 5453

有乙個文字串s和乙個模式串p,現在需要查詢模式串p在文字串s中的位置,簡單的考慮,可以用以下方法:

1、將模式串的第乙個字元與文字串的第乙個字元進行比較,如果不相同則模式串整體後移一位,繼續1步驟;如果相同則跳轉步驟2

2、模式串的第乙個字元與文字串的第乙個字元相同,則繼續比較第二個字元,如果不相同則模式串整體後移,跳轉到步驟1;如果相同則繼續下乙個字元的比較

3、上述步驟重複,直到匹配成功,或者已經匹配到文字串的最後乙個字元,匹配失敗。

從暴力匹配演算法可以發現,這種方法的時間複雜度是非常高的,為o(n*m),其中n為字串長度,m為模式串長度。

而kmp演算法則可以實現時間複雜度為o(n+m),效率更加的快。簡單的來說,kmp演算法相比暴力匹配演算法,在進行匹配的時候,不再是每次乙個字元的移動遍歷,而是先計算出一張失配表,按照失配值進行移動。

即,kmp演算法=暴力匹配演算法+失配表

假設有文字串「bbc abcdab abcdabcdabde」和模式串「abcdabd」,現在進行匹配

(1)首先,按照暴力匹配的思路,先對文字串和模式串的第乙個字元進行比較,不相同則向後移動一位

(2)繼續匹配,直到文字串與模式串的第乙個字元相同

(3)再次對文字串與字串的第二個字元進行對比

(4)重複執行,到這裡文字串和模式串出現了不同的字元

這個地方就是暴力匹配法和kmp演算法不同的分割點,按照暴力匹配的思路,出現不同則模式串整體後移一位,如下:

但是我們可以直觀的理解到,接下來的這一串文字我們在之前已經匹配過了,這樣的操作相當於我們再一次重複了上一輪的操作,效率非常的低。

而kmp演算法與暴力匹配演算法的不同在於,失配表。

(5)如下圖存在失配表,顧名思義就是在匹配失敗的時候進行查詢的表,具體計算方式後面再詳解

在空格與d不匹配的時候,前面已匹配成功字元數為6,查表最後乙個匹配字元b的失配值為2,可按下方公式計算:

移動位數 = 已匹配的字元數 - 對應的失配值
在這裡計算出來的移動位數為4

(6)移動4位之後,繼續進行匹配

可以看到,這裡模式串前面的兩個字元ab和字串是相同的,之後繼續上述步驟,已匹配字元2,最後乙個字元b的失配值為0,移動位數為2

(7)重複上述過程,直到匹配成功

(1)概念

字首,指除了最後乙個字元以外,乙個字串的全部頭部組合

字尾,指除了第乙個字元以外,乙個字串的全部尾部組合

失配值,指字首和字尾的最長的共有元素的長度

(2)實現

如有模式串「abcdabd」,失配表計算方式如下:

「a」的字首和字尾都為空,共有元素長度為0,即表中「a」對應位置失配值為0;

「ab」的字首為[a],字尾為[b],共有元素長度為0,即表中「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。

即,最後計算出來的對應模式串的失配值為,0000120

1、

模式匹配 KMP演算法

字串匹配演算法 include includeusing namespace std define ok 1 define error 0 define overflow 2 typedef int status define maxstrlen 255 使用者可在255以內定義最長串長 typed...

模式匹配KMP演算法

前些日子在為目前該學習什麼而苦惱,就問了一下已經從事多年軟體開發的表哥,他說乙個程式設計師要走的遠,就要學好資料結構和演算法,於是我就重新開始學習資料結構和演算法了 拿起以前上過的資料結構看,看到第四章串的模式匹配時,頗感興趣,就寫了一下程式,實踐了一下。感覺還蠻爽,於是就把以下幾個重要的函式放在此...

KMP模式匹配演算法

首先,這是由knuth morris和prattle三人設計的線性時間字串匹配演算法。這裡就不仔細的講解,網上有更好的講解,在這推薦幾個自己當時學習的kmp所看到的較好理解的 這裡附上自己所學的 includeusing namespace std s 是主串 p 是模式串 int next 100...