擴充套件KMP超詳細理解

2021-09-06 23:16:00 字數 2504 閱讀 9618

本文**,希望原博主不要介意,介意的話我可以刪掉

前文已經介紹了經典的kmp演算法,本文繼續介紹kmp演算法的擴充套件,即擴充套件kmp演算法。

問題定義:給定兩個字串s和t(長度分別為n和m),下標從0開始,定義extend[i]等於s[i]...s[n-1]與t的最長相同字首的長度,求出所有的extend[i]。舉個例子,看下表:i0

1234

567s

aaaa

abbb

taaa

aacextend[i]54

3210

00為什麼說這是kmp演算法的擴充套件呢?顯然,如果在s的某個位置i有extend[i]等於m,則可知在s中找到了匹配串t,並且匹配的首位置是i。而且,擴充套件kmp演算法可以找到s中所有t的匹配。接下來具體介紹下這個演算法。

如上圖,假設當前遍歷到s串位置i,即extend[0]...extend[i - 1]這i個位置的值已經計算得到。設定兩個變數,a和p。p代表以a為起始位置的字元匹配成功的最右邊界,也就是"p = 最後乙個匹配成功位置 + 1"。相較於字串t得出,s[a...p)等於t[0...p-a)

再定義乙個輔助陣列int next,其中next[i]含義為:t[i]...t[m - 1]與t的最長相同字首長度,m為串t的長度。舉個例子:i0

s[i]對應t[i - a],如果i + next[i - a] < p,如上圖,三個橢圓長度相同,根據next陣列的定義,此時extend[i] = next[i - a]

如果i + next[i - a] == p呢?如上圖,三個橢圓都是完全相同的,s[p] != t[p - a]t[p - i] != t[p - a],但s[p]有可能等於t[p - i],所以我們可以直接從s[p]t[p - i]開始往後匹配,加快了速度。

如果i + next[i - a] > p呢?那說明s[i...p)t[i-a...p-a)相同,注意到s[p] != t[p - a]t[p - i] == t[p - a],也就是說s[p] != t[p - i],所以就沒有繼續往下判斷的必要了,我們可以直接將extend[i]賦值為p - i

(5)最後,就是求解next陣列。我們再來看下next[i]extend[i]的定義:

恍然大悟,求解next[i]的過程不就是t自己和自己的乙個匹配過程嘛,下面直接看**。

#include #include using namespace std;

/* 求解 t 中 next,注釋參考 getextend() */

void getnext(string & t, int & m, int next)

else

next[i] = next[i - a];

}}/* 求解 extend */

void getextend(string & s, int & n, string & t, int & m, int extend, int next)

else

extend[i] = next[i - a];

}}int main()

return 0;

}

資料測試:

aaaaabbb

aaaaac

next: 6 4 3 2 1 0

extend: 5 4 3 2 1 0 0 0

abcdef

next: 3 0 0

extend: 0 0 0

超詳細!終於搞明白KMP演算法

小夥伴們好久不見,今天將開設 資料結構與演算法 專欄,一起梳理一遍硬核課程的重要知識點,那我們開始吧 字串匹配是計算機的基本任務之一,舉個栗子,有乙個字串 aaaaaaca 我想知道裡面是否包含另乙個字串 aaaac 該怎麼辦?這裡就會使用到串的模式匹配演算法,最常見的分別是傳統的brute for...

KMP 擴充套件KMP

本文將不斷加入例題,稍安勿躁,今天的總結爭取9 30寫完.kmp,中文名字叫字串匹配,用於解決一類字串匹配問題.先下一些定義 首先我們先想一想 nxt i 對於求解問題有怎樣的幫助.我們對於每乙個 t i s 1 的位置都匹配一次,這樣子複雜度為 theta n m 的.考慮在暴力匹配中其實我們不一...

擴充套件kmp

出自 2 i k l 1 p k,即i l p。這時,首先可以知道a i.p 和b 0.p i 是相等的 因為a i.p b i k.p k 而i k l 1 p k,由b 0.l 1 b i k.i k l 1 可得b 0.p i b i k.p k 即a i.p b 0.p i 然後,對於a p...