1. 程式人生 > >什麽是KMP算法?KMP算法推導

什麽是KMP算法?KMP算法推導

下標 code 條件 logs 沒有 str left back 除了

花了大概3天時間,了解,理解,推理KMP算法,這裏做一次總結!希望能給看到的人帶來幫助!!

1.什麽是KMP算法?

在主串Str中查找模式串Pattern的方法中,有一種方式叫KMP算法

KMP算法是在模式串字符與主串字符匹配失配時,利用已經匹配的模式串字符子集的最大塊對稱性,讓模式串盡量後移的算法。

這裏有3個概念:失配,已經匹配的模式串子集,塊對稱性

失配和隱含信息

在模式串的字符與主串字符比較的過程中,字符相等就是匹配,字符不等就是失配;

隱含信息是,失配之前,都是匹配

在主串S[0,100]中查找模式串P[0,6],從下標0開始查找,在下標為5的位置失配,記為P[0,5]失配,則有

P[5]!=S[5],又有S[0,4]=P[0,4]

則P[0,4]都是匹配的!

已經匹配的模式串子集

接上一例,模式串是P[0,6],而P[0,4]都是匹配的,所以,已經匹配的模式串子集有

Pcs={ P[0,4],P[0,3],P[0,2],P[0,1],P[0] }

2.塊對稱性

什麽是塊對稱性?

塊對稱性,就是字符串前綴,後綴重疊;

比如: a b c d a b c

前綴:除了最後一個字母外,所有的前綴子集;

如: a,ab,abc,abcd,abcda,abcdab

後綴:除了第一個字母外,所有的後綴子集

如: bcdabc,cdabc,dabc,abc,bc,c

這裏前綴abc和後綴abc重合

技術分享圖片

可以把這個重合看做,相對於綠塊對稱,所以叫它塊對稱性

塊對稱有很多種;比如:

技術分享圖片

咦?大家都在一水平排,怎麽有一個飛起來了?

飛起來那個將在利用最大快對稱性 小節講解。

塊有什麽特點?

特點:擁有塊對稱性的字符串至少有2塊對稱重合的的部分

分析,對稱是修飾,重合是關鍵。而且重合的是前綴和後綴。

如何利用塊對稱性?

技術分享圖片

模式串如圖,如果模式串和主串Str匹配的過程中,在l這失配即P[0,7]失配,你會怎樣?

分析,

第一,模式串的P[0,6]和主串放入S[0,6]是完全匹配的

第二,P[0,6]串是塊對稱的!

因為P[0,6]剛好有塊對稱性,我可以把前綴abc移動到後綴abc的位置,然後讓d與主串去匹配,這樣就利用快對稱性了對吧?

技術分享圖片

總結,可以在P[7]失配時,看失配字符的最大前綴P[0,6]是否有塊對稱性,如果有,我們就可以向右移動模式串,讓左邊的重合前綴移動到右邊的重合後綴,再讓模式串和主串比較!

利用最大塊對稱性?什麽意思?

什麽是KMP算法小節裏,說KMP是在模式串與主串匹配失配時,利用已經匹配的模式串子集的最大塊對稱性,盡量讓模式串右移!這裏的利用最大塊對稱性是什麽意思?

這裏利用最大塊對稱性意味著可能發生遞歸

把上個案例的d換成k,如下圖:

技術分享圖片

KMP算法會預先計算出模式串所有前綴子集中哪些前綴有塊對稱性,在這些有塊對稱性的前綴的後一個字符失配時,利用其塊對稱性;

比如本例中P[0,6]有塊對稱性,那麽在P[0,7]也就是l失配時,

會先利用P[0,6]的塊對稱性,即P[0,2]和P[4,6]相遇於字符P[3]塊對稱,

如果不行,會看P[0,2]塊對稱重合的部分有沒有塊對稱性,

有,就利用;以此類推,一直遞歸到沒有塊對稱性為止。

塊對稱長度的意義-編程

第一次移動中,3是什麽?塊對稱重合長度,也是下次開始比較的位置!

第二次移動中,1是什麽?塊對稱重合長度,也是下次開始比較的位置!

技術分享圖片

3.next數組推導-計算塊對稱性

單獨的塊對稱性是沒有意義的,塊對稱性必須結合上失配,才能利用塊對稱性!

所以,應該計算出Pattern所有前綴子集失配時的塊對稱性!放到一個叫next[]數組的地方!

如何計算呢?

next數組是計算失配時的塊對稱性,

當第1個字符失配時,壓根就沒有前綴後綴的說法,所以有next[0]是不存在塊對稱性的,記為next[0]=-1;

當第2個字符失配時,它的子集只有1個字符,也是沒有前綴後綴,沒有塊對稱性,所以記為next[1]=0;

再看圖,對於值k,已有p0 p1, ..., pk-1 = pj-k pj-k+1, ..., pj-1,則有next[j] = k。

next[j] = k代表了什麽呢?

代表在Pj之前,有長度為k的塊對稱性,有2個長度為k的重合部分。

總結一下,前提條件如下:

條件1.next[0]是不存在的,next[1]=0

條件2.對於下標值k,已有p0 p1, ..., pk-1 = pj-k pj-k+1, ..., pj-1,則有next[j] = k

next[]數組是從0開始被初始的,如果我們能推導出next[j+1] = 什麽,是不是就可以計算出next[]數組? 是吧

下面來推導next[j+1]

技術分享圖片

已知:

p0 p1, ..., pk-1 = pj-k pj-k+1, ..., pj-1,==》 next[j] = k

如果pk與pj匹配

則有p0 p1, ..., pk-1,pk = pj-k pj-k+1, ..., pj-1pj,==》 next[j+1] = k+1;

原來有2個長度為k的對稱重合部分,pk與pj匹配後,2個長度為k對稱重合的部分又有了1對字符重合,所以有next[j+1]=k+1;

再看圖,next[j]=k,當pj失配時,下一次用pk去和主串匹配;所以next[j]的實際意義是,當pj失配時,下一次應該用哪個字符去和主串匹配!!

條件3.next[ ]數組的值就是當次失配時,下一次匹配的位置!

如果pk與pj不匹配,next[j+1]=?

next[j+1]的實際意義是,p[0,j+1]的pj+1失配時,p[0,j]的塊對稱重合長度,也是下一次匹配時應該用模式串的哪個字符與主串匹配,哪個字符的下標就是next[j+1]。

具體詳參塊對稱長度的意義-編程

下一次用哪個字符比較呢?

技術分享圖片

a1=p0 p1,...,pk-1,a2=pj-k pj-k+1,...,pj-1;a1==a2

當pk與pj不匹配時,不能用a1替換a2,如圖綠叉;

因為a2是離與主串最近的部分,所以這時候應該分析a2是否有塊對稱性,

如果a2有塊對稱性,那麽a1也有塊對稱性,如圖綠框;

所以,這時應該分析p[0,k]的塊對稱性,也就是next[k]

設x1與x2關於綠框對稱;

x3與x4關於綠框對稱;

那麽把x1移動到x4的位置,是不是就可以最大利用上;

所以next[j+1]=next[k];

總結一下

If ( p[k] == p[j] ) next[j+1]=k+1

else next[k+1]= next[k]

4.參考文獻

https://blog.csdn.net/v_july_v/article/details/7041827

http://www.codeceo.com/kmp-next-array.html

https://www.zhihu.com/question/21474082 next數組推導

https://blog.csdn.net/yearn520/article/details/6729426 next數組推到原則

https://www.xahkbg.com/

KMP中,計算目標查詢串T的next[]數組是關鍵;

https://zhuanlan.zhihu.com/p/24274982

https://blog.csdn.net/yearn520/article/details/6729426

http://www.cnblogs.com/c-cloud/p/3224788.html

https://zhuanlan.zhihu.com/p/24649304

什麽是KMP算法?KMP算法推導