2019 8 6 拓展kmp演算法

2021-09-25 22:33:53 字數 2693 閱讀 4798

首先感謝2023年一位博主寫的部落格

kmp

寫的很詳細

不過有一點小小的錯誤

我就在此基礎上用圖來表示

我把大家視為啥都不懂的小白

現在我們有乙個字串a

我們有一天突然想要知道對於a的每一位開始

最多能和多長的a的字首完全相等?

比如我們可愛的ywwyww字串

就是這樣的乙個陣列:6 0 0 3 0 0

第0位開始和原來的字串完全相同,所以是6

第1位開始就和y不同

第2位開始就和y不同

第3位開始和原來的字首yww相同,所以是3

……現在搞懂了我們想要搞懂的問題

首先我們探求一下這個陣列的性質

假設這個陣列名字叫做next(編碼的時候不要用next命名,因為next在stl裡有定義)

另t=next[i]

那麼next[i]的意義就是說a[0]到a[t-1] 和 a[i]到a[i+t-1] 的字元完全相同

比如上面的栗子就是i等於3時next[3]=3。代表a[0]到a[2] 和 a[3]到a[5]的字元完全相同。

我們完成了第一步

第二步我們開始探求遞推關係

首先next[0]肯定是a陣列的長度啦

next[1]可以通過下方**求出

int a=

0,tlen=

strlen

(a),next[0]

=tlen;

while

(a1&&t[a]

==t[a+1]

) a++

;next[1]

=a;

下面就是我們的假設環節

假設我們已經知道了next[0]到next[k-1]的數值

0到k-1呢存在乙個數a

使得0<=a<=k-1條件下a+next[a]-1最大

稍微想一下就知道max(a+next[a]-1)就是我們的字首能夠匹配的最大距離

我們令p=max(a+next[a]-1)

好的,現在我們想求next[k]

咋辦呢?

我們畫乙個數軸,把所有已知量給寫出來

縱方向相對的就是相同的字元

理解這個後

我們引入l=next[k-a]這個量

可能你現在覺得這個什麼鬼量啊,等會你就清楚了

我們簡單分析一下

next[k-a]代表什麼呢?

代表a[0]到a[l-1] 和 a[k-a]到a[k-a+l-1]的所有字元相同~

現在我們想一想k-a+l-1在數軸裡什麼位置呢?

我們重畫一下

第一種情況:k-a+l-1<=p-a,就是 k+l-1<=p

數軸變成了這樣

又由我們剛才得到的next[k-a]的作用:a[0]到a[l-1] 和 a[k-a]到a[k-a+l-1]的所有字元相同~

而通過數軸我們看出a[k]到a[k+l-1] 和 a[k-a]到a[k-a+l-1] 的所有字元相同!

所以得出結論:a[0]到a[l-1] 和 a[k]到a[k+l-1] 的所有字元相同~

所以我們的next[k]的範圍肯定》=l,對吧

現在想想next[k]有可能大於l嗎??

思考一下如果next[k]>l,那麼a[k+l]就要和a[k-a+l]相同

那麼a[l]就要和a[k-a+l]相同!!!

那麼我們的next[k-a]就要變大了

這顯然不可能

所以我們的next[k]就定調了

當k+l-1<=p時,next[k]=l。

如果看懂了前面的

我們進入第二種情況:k-a+l-1>p-a,就是 k+l-1>p

此時數軸是這樣的

那麼我們同樣有這個結論:a[0]到a[l-1] 和 a[k]到a[k+l-1] 的所有字元相同~

l含義同上

此刻我們分析一下由於k+l-1>p,所以p-k<=l-1

誒?此刻我們再分析一下

由於p-k<=l-1

a[0]到a[p-k]是不是和 a[k]到a[p]相同了?

是不是很驚喜?

我們的next[k]的範圍不就是》=p-k+1了嘛

此時想想

能不能大於p-k+1呢?

答案是可以的

因為從a[p+1]開始我們就沒有再匹配過了

也就無從知曉是否匹配

於是我們開始最笨的方法

乙個乙個匹配

最終乙個不匹配或者超出了tlen範圍

那麼next[k]就出來了

在這個過程中,a,p,l是一直在維護的

這個真的搞了我一天。。。

附上**

void

pre_kmp

(char s)

else

}}

那麼我們有兩個字串a和b的話,對於a的每一位開始

最多能和多長的b的字首完全相等?

我們是不是只需要預處理b的next陣列,就可以求出這個問題了?

void

getextend

(char

*s,char

*t)else extend[k]

=l;}

}

真搞了我一天,jio的好走一波點贊關注?

拓展KMP演算法

問題模型 給定字串s和子串t,s的長度為n,t的長度為m 求字串t與字串s的每乙個字尾d的最長公共字首。拓展kmp演算法 假設 extend 陣列 extend i 表示 t 與 s i,n 的最長公共字首,目的是求出所有的 extend 0 n 1 注意到,如果存在extend i m,則說明 t...

拓展kmp演算法總結

演算法總結第二彈,上次總結了下kmp,這次就來拓展kmp吧。拓展kmp是對kmp演算法的擴充套件,它解決如下問題 定義母串s,和字串t,設s的長度為n,t的長度為m,求t與s的每乙個字尾的最長公共字首,也就是說,設extend陣列,extend i 表示t與s i,n 1 的最長公共字首,要求出所有...

拓展kmp演算法總結

演算法總結第二彈,上次總結了下kmp,這次就來拓展kmp吧。拓展kmp是對kmp演算法的擴充套件,它解決如下問題 定義母串s,和字串t,設s的長度為n,t的長度為m,求t與s的每乙個字尾的最長公共字首,也就是說,設extend陣列,extend i 表示t與s i,n 1 的最長公共字首,要求出所有...