KMP演算法之從懵逼到入門

2021-08-20 07:56:32 字數 2763 閱讀 3606

寫本文的目的:

1.加深自己的理解,以便自己日後複習

2.給看到此文的人一點啟發

kmp演算法看懂了就覺得特別簡單,思路也好理解,但是看不懂之前,查各種資料看大佬的部落格,都很懵逼......

1.  演算法過程解釋

首先,字串"bbcabcdab abcdabcdabde"的第乙個字元與搜尋詞"abcdabd"的第乙個字元,進行比較。因為b與a不匹配,所以搜尋詞後移一位。

就這樣,直到字串有乙個字元,與搜尋詞的第乙個字元相同為止。

接著比較字串和搜尋詞的下乙個字元,還是相同。

直到字串有乙個字元,與搜尋詞對應的字元不相同為止。

這時,最自然的反應是,將搜尋詞整體後移一位,即從上圖b處再從頭逐個比較。這樣做雖然可行,但是效率很差,因為你要把搜尋的初始位置移到已經比較過的位置,重比一遍。

乙個基本事實是,當空格與d不匹配時,你其實知道前面六個字元是"abcdab"。kmp演算法的想法是,此時不只移動一位,移動數是已經比較的字元數 - 最後乙個匹配字元所對應的部分匹配值,這個部分匹配值實質上就是字串頭部和尾部重複部分的最大長度。因此就有了部分匹配值陣列:

已知空格與d不匹配時,前面六個字元"abcdab"是匹配的。查表可知,最後乙個匹配字元b對應的"部分匹配值"為2,因此向後移動的位數為已匹配的字元數減去對應的部分匹配值,即6-2=4。

因為空格與a不匹配,繼續後移一位。

逐位比較,直到發現c與d不匹配。於是,移動位數為 6 - 2,繼續將搜尋詞向後移動4位。

逐位比較,直到搜尋詞的最後一位,發現完全匹配,於是搜尋完成。如果需要找出全部的匹配,移動位數為7 - 0,再將搜尋詞向後移動7位,剩下的操作就重複了。

首先,要了解兩個概念:字首和字尾。

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

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

"部分匹配值"就是"字首"和"字尾"的最長的共有元素的長度。以"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。  

kmp演算法的核心思想(個人理解):根據子串確定每次匹配失敗的時候主串開始比較位向前移動的位數,位數=已經比較的字元數 - 最後乙個匹配字元所對應的部分匹配值,這個就是kmp和暴力匹配演算法的根本區別

#include #include 

#include

void getnext(char a,int l,int

next)

else

}if(k!=0)//

k此時不在a[0]的位置上

else}}

}void kmp(char str,char

a)else

if(str[i]==a[j]&&j!=0

)

else

if(str[i]!=a[j]&&j==0

)

else

if(str[i]!=a[j]&&j!=0

)

if(j==l)//

匹配成功的條件

}}int

main()

參考:

不足錯誤之處歡迎拍磚!!!!!

KMP演算法入門

kmp演算法的核心,是乙個被稱為部分匹配表 partial match table 的陣列。我覺得理解kmp的最大障礙就是很多人在看了很多關於kmp的文章之後,仍然搞不懂pmt中的值代表了什麼意思。這裡我們拋開所有的枝枝蔓蔓,先來解釋一下這個資料到底是什麼。對於字串 abababca 它的pmt如下...

cgroup從入門到懵圈 cgroup概念

從今天起,我要開始寫部落格了。先立個flag在這兒 兩周一篇。萬事開頭難,中間不容易,最後會放棄。請各位看官監督 雖然似乎肯定沒有人看 之前有接觸過cgroup,但東西都是同事在做 羨慕 理解不深。所以這個系列的文件,我假裝自己是cgroup菜雞 其實我不需要假裝 從零開始學習cgroup。cgro...

kmp從入門到放棄

標籤 kmp 擴充套件kmp 給你兩個字串,你需要回答,b串是否是a串的子串 a串是否包含b串 a aaaaaaaaaaaaaaaaaaaaaaaaaab b aaaaaaaab 最壞狀態 o mn 一般做法 for 列舉b在a串中的起始位置 for 向後比較ab是否相等 o n m 傳說中的kmp...