資料結構 模式匹配 KMP演算法

2021-10-21 11:53:13 字數 1526 閱讀 3648

模式匹配:在主串中找到與模式串相同的子串,並返回其位置

在討論kmp時,先來看看樸素模式匹配有什麼問題。樸素模式匹配的思路是把主串中與模式串長度相同的所有子串搞出來,挨個與模式串對比,有乙個字元不匹配時,立即放棄當前子串,轉而索引下乙個子串。在最壞的情況中,主串指標向前走m步,回退m-1步(前m-1個字元都匹配,到最後乙個字元不匹配,白幹了),模式串也不斷在回退,導致演算法時間複雜度很高。由此引入了kmp演算法,需要注意的是只有在子串與模式串經常能部分匹配的時候,kmp才比樸素模式匹配優秀很多。

思路讓主串指標不回退,每次匹配失敗時只回退模式串的指標

工具:next陣列來標記模式串回退的位置,當j=k且發現字元不匹配時,模式串指標回溯到j=next[k]

當第j個字元匹配失敗,將模式串的前j-1個字元組成的串記為s,next[j]=s最長相等的前字尾長度+1

串的字首:包含第乙個字元單不包含最後乙個字元的子串

串的字尾:包含最後乙個字元但是不包含第乙個字元的子串

前字尾是正著比較的,注意相等的前字尾可以有部分重疊!

規定:next[0]=空,next[1]=0,next[2]=1

看起來好像很複雜,但是只要搞懂乙個道理,next中儲存的是回退的位置,也是下一次匹配重新開始的位置,這個位置要避免之前重複的比較,舉個例子。(next陣列只與模式串有關)

上圖可知,對第乙個a的比較一定是多餘的,所以直接從b處開始比較即可,第乙個a一定匹配。再來看c處發生不匹配的情況,此時主串的尾巴處一定是abaab

所以c處不匹配只用從3位置開始重新比較就好了。用書面語言就是next[j]=s最長相等的前字尾長度+1

接下來要進一步談的是kmp演算法的優化

確定nextval[j]的辦法:從左到右掃瞄next陣列,重複出現的字元的nextval值與它第一次出現時相同,進一步提高效率。

如圖,假如在第四個a發生不匹配,同樣第一二三個a肯定也是不匹配,最終通過三次索引next陣列回到第乙個a的位置,浪費了時間。用nextval陣列就一步到位了。

資料結構 模式匹配kmp演算法

暴力演算法 暴力演算法 intindex sstring s,sstring t,int pos else if j t 0 return i t 0 else return0 kmp演算法 next陣列的求法 例子 abaabcac 模式串的下標從1開始 第一位固定為0 第二位固定為1 從第三位 ...

資料結構 模式匹配演算法

模式匹配 子串的定位操作。模式匹配演算法主要有 1 樸素的模式匹配演算法 2 kmp模式匹配演算法 next陣列 3 改進的kmp模式匹配演算法 nextval陣列 比較 1,時間複雜度 樸素的模式匹配演算法為o n m 1 m 效率很差,kmp演算法為o m n 大大避免重複遍歷情況。2,改進的k...

資料結構 串 串的模式匹配 KMP演算法

head.h include includeusing namespace std class string void string getstring void string getsubstring void string kmp cout kmp method called main.cpp ...