擴充套件 KMP

2021-09-26 06:18:38 字數 2120 閱讀 7998

目錄

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

1234

567s

aaaa

abbb

taaa

aacextend[i]543

2100

0 為什麼說這是 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

1234

5taa

aaac

next[i]64

3210

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

(3)如果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]開始往後匹配,加快了速度。

(4)如果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]的定義:

#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 擴充套件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...

擴充套件KMP

拖了這麼久,終於打出擴充套件kmp了。並不長,但是細節很多。最好把模板背下來,實在背不下來就根據原理去推。相比於kmp來說擴充套件kmp的應用範圍更廣,更靈活。它的ext i 與kmp的next i 的區別就是next i 表示長度最大的一段s i next i 1 i t 1 next i ext...