KMP字串匹配演算法

2021-10-03 11:10:08 字數 2578 閱讀 7023

演算法其實並不難,但是講的費勁,看的也費勁……

**問題描述:**給兩個字串str和ptr,求str中是否有和ptr相同的子串並找出這個子串在str中的位置

這個問題的暴力演算法很好想:從頭開始乙個字母乙個字母地遍歷str,然後對照ptr是否是從這個位置開始的子串。而kmp演算法利用了前字尾的特殊性,簡化了時間複雜度。

(從o(mn)變為o(m+n))

ps:演算法思想可以參考:

戳我看敲好理解的kmp演算法鴨

(1)首先介紹字首字尾:如abcdef,字首就是a,ab,abc……而字尾就是f,ef,def……理解前字尾以後我們引入乙個陣列next,next中存放的就是到i這個位置(包括這個位置)之前前字尾相等且最長的情況。

如果不是很理解我們舉個栗子 (劃掉)例子 :在前面提到的**中的兩個字串

str:bbcabcdabababcdabcdabde

ptr:---------------------- abcdabd------------- (絕了,為什麼不能用空

格對齊,只好這樣了)

next[ptr]可以對應寫出:

next[1]=0

next[2]=0

next[3]=0

next[4]=0

next[5]=1(相同前字尾:a)

next[6]=2(相同前字尾:ab)

next[7]=0

可以看出:ptr在d前面的一串都適配了,但是d和c不適配。

那麼發現不匹配的時候,難道我們是將ptr位置直接++,然後繼續比對嗎?其實不必。

我們可以發現,ptr在d前面的序列abcdab中,字首ab和字尾ab是相等的,即next[6]=2。重點來了!!那麼我們可以直接把ptr從何前面移動到後面這個加粗的ab這裡。因為我們已經從next陣列中知道了在6這個位置,有乙個長度為2的字尾等於前面長度為2的字首。那麼就說明直接將ptr移到這個位置,剛好可以匹配。

移動4=6-2

即公式:要移動的位置=已經匹配的數x-next[x]

可能會有人有疑惑,比如說:

str:ab***ab***xxabc

ptr:ab***ab***xxabd

next[14]=2-------------↑這兒

那麼就把ptr:--------ab***ab***xxabd

為什麼ptr不直接跳過了中間的ab段而移動到了後面的ab段

其實可以舉個反慄,如果中間那段ab開頭的字串和ptr匹配,那麼就有更長的前字尾,就和之前定下的next[14]=2不符合了。

然後我們看怎麼求next。直接貼上**,這裡的next和上面的next不一樣。。這裡的next求的是到這個位置的最長長度前字尾-1!記住要減1!因為後面**從0開始計數,減一才能對應。

void

kmp_next

(char

*s)if

(s[k+1]

== s[i])

next[i]

= k;

}}

哇,看得我腦殼疼。

最難理解的應該是k=next[k]這一行。不方,其實這就是乙個回退操作

指路:next演算法

從求next開始那段,講得很清楚了

全**:

#include

#include

using

namespace std;

#define maxn 101

int nextt[maxn]

;void

cal_next

(string str)

if(str[k+1]

==str[i]

) nextt[i]

=k;}

}int

kmp(string str,string ptr)

return-1

;}intmain()

(1)如果len可以被len - next[len]整除,則表明字串s可以完全由迴圈節迴圈組成,迴圈週期t=len/l。

(2)如果不能,說明還需要再新增幾個字母才能補全。需要補的個數是迴圈個數l-len%l=l-(len-l)%l=l-next[len]%l,l=len-next[len]。

**:(1)關於next的求取

nextt[i]:

nextt[0]=-1

nextt[1]=0;

這兩個是固定的

i=1~n;訪問的是當前這個位置(注意!不是從0開始!)有多少個最大相同前字尾

這樣,雖然string是從下標0開始的,但是把它往後移了一位~

如果k=-1直接加一了

#include

#include

#define maxn 1000000+10

using

namespace std;

int nextt[maxn]

;void

cal_next

(string str)

nextt[

++i]

=++k;}}

intmain()

} cout<}}

KMP演算法 字串匹配

kmp演算法基本思想 我們在用常規的思想做 字串匹配時候是 如 對如 字元如果 t abab 用p ba 去匹配,常規思路是 看 t 第乙個元素 a 是否 和p 的乙個 b 匹配 匹配的話 檢視各自的第二個元素,不匹配 則將 t 串的 第二個元素開始 和 p 的第乙個匹配,如此 一步一步 的後移 來...

KMP字串匹配演算法

kmp核心思想 計算模式串的next陣列,主串的索引在比較的過程中不回朔 ifndef kmp h define kmp h class kmp endif include kmp.h include include include using namespace std int kmp calcu...

KMP字串匹配演算法

在介紹kmp演算法之前,先介紹一下bf演算法。一.bf演算法 bf演算法是普通的模式匹配演算法,bf演算法的思想就是將目標串s的第乙個字元與模式串p的第乙個字元進行匹配,若相等,則繼續比較s的第二個字元和p的第二個字元 若不相等,則比較s的第二個字元和p的第乙個字元,依次比較下去,直到得出最後的匹配...