首先感謝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 的最長公共字首,要求出所有...