注:模式串指我們要找是不是出現的串,主串指我們匹配的物件。
一種由knuth(d.e.knuth)、morris(j.h.morris)和pratt(v.r.pratt)三人設計的線性時間字串匹配演算法。
其實就是利用已經匹配過的字元,也就是在中間的每乙個位置,就斷開了。利用前面的部分去設定,下次尋找的點。
普通的就是這個失敗,就返回剛開始的位置的下乙個。繼續尋找。不斷的,不斷的。。。
kmp的話,就是看你找過且對的上的部分的規律,通過這個規律,我們判斷下一次找的點的位置,從模式串裡面的那個位置開始。
比如下面的乙個例子:00
0000
0100
1當1不匹配的時候,我們是返回第二個位置接著尋找呢?(當然kmp也是這樣的,但是我們指只要匹配不成功,就下面乙個位置繼續,重新開始的那種普通匹配。)00
0000
1001
以上的尋找,怎麼樣改善呢?
他通過判斷制定乙個next的規則,進行模式串下一次的位置判斷點。就可以直接判斷。從而實現o(n+m)的時間複雜度。
重點:每乙個next的值,都是表示前看,後看的最長公共長度。
(以該點後看,和從開始往後看)
注:0特殊注意一下,1表示如果不相等,要返回的位置 = 1 -1=0,第乙個0表示邊界,後面的表示返回的位置(下標從1開始)
就幾個例子,解釋一下。好吧。
abcdefg這個例子:next為0 1 1 1 1 1 1;
aaaaa這個例子:next就是 0 1 2 3 4 了。
(最後乙個a的next為4,表示如果不相等就要返回i = 3的位置區)
我舉乙個例子:假設條件是 子串: 0001,主串:00000001.00
0000
0100
01
現在的情況是:匹配到了j = 4的時候,二者不相同。那麼我們應該讓j跳到**去呢?(普通尋找和kmp的最大區別點)
普通尋找:j = 0,(從頭開始繼續),kmp:觀察結束的位置,觀察已經匹配好了的串的規律。
由題目可以看出:000 已經匹配好了的。那麼我是不是可以認為這樣呢?
0
0
000
0010
0
0
1前面 vision[0~j-1]是已經匹配好了的,說明如果我從匹配好了的裡面找出"折點",是不是就可以不用從新開始了呢?
折點:在以匹配的串中,找出迴圈點的位置,(從開始尋找和自己點往前尋找比如abaab,折點在第三個a上面)
這個較特殊:我們換乙個 子串:abaabc 主串:abaabaabc這個來找這個折點ab
aabaab
caba
abc
我們**到i = j = 5的時候斷了。這個時候,我們就要分析了折點在哪?
比如不存在折點問題:那麼我想問你換乙個位置重新匹配可以成功嗎?答案顯然是不存在的。
比如 abcdef,在f斷了。那也表示著abcde匹配成功了,還表示著如果移乙個位置重新開始,從b,c,d,e,f開始接著尋找可能找到嗎?答案:不可能。
回到上面的問題:尋找折點:abaaab匹配成功了,折點在第乙個b上面。
(前面後面看只有ab了。考慮第三個的話,前面為:aba,後面:aab,不相等。所以在b上面。)
那麼我們下次尋找就不需要從新尋找,只需要從b的後面乙個開始接著匹配就可以了。
next差不多也就是講完了。kmp的玄機也就是這樣了。
當我們知道這些next,又有什麼用呢?
當然有用了,結合next陣列,在加上主串的尋找我們可以實現o(n+m)的時間。也就實現了時間複雜度的縮小的作用了。
還可以通過next反覆在主串中尋找重複的子串,(記錄位置,判斷個數,最長字首等等問題)
要想重複的搜尋,有多少個。
只需要找到之後讓k = 0.重新找。(if(k == len) k = 0,cnt++;)
我的**是學校的oj,以0為開頭的kmp演算法,有可能看不懂,不過沒關係,看得懂前面的就可以了。(next[i],表示的是0到i-1的位置的相同長度!0特殊注意一下,1表示如果不相等,要返回的位置)
#include #include #include using namespace std;
void get_next(char *str,int len,int *next)
}void print_next(int *next,int len)
}return k;
}int main()
return 0;
}
其實,我就是聽我們老師講了一節課,自己的總結。怕忘了。
最後,謝謝,各位大佬的**!
擴充套件KMP 記錄學習過程
首先看了幾篇部落格,發現還得耐下心來理解,動手畫圖 才能理解倆字串還有陣列之間神奇的關係 這篇部落格圖不錯 擴充套件kmp 一開始假設求出了 next陣列,然後去求extend陣列,然後方法一樣 next陣列可以自己求自己 include include define s 1000 define t...
c 學習KMP演算法的記錄
kmp大名鼎鼎,看過面經說手撕kmp,趕緊複習一下。這個人的kmp實話實說寫的非常好!傳送一下子 void get next string t,vector next else int main string t vector next t.size get next t,next int i 0,...
KMP演算法記錄
kmp演算法這篇寫的很好,非常好理解 這個演算法用來做字串匹配。字串匹配是計算機的基本任務之一。如果給出兩個字串text 和 pattern 需要判斷字串pattern 是否為字串text 的子串。一般把字串text 稱為文字串,而把字串pattern 稱為模式串。舉例來說,有乙個字串 bbc ab...