KMP算法之Next數組詳解


最近剛好學到了kmp算法,對我來說還蠻難的,原理還好理解,就是next數組的求解讓我很懵

旁聽了一下隔壁班大佬的分享,覺得他們講得特別好,就想來記錄一下

最長公共前后綴

kmp算法首先要找“最長公共前后綴”,其定義為:A的“最長公共前后綴”是“A中以最后一個字符結尾的非前綴子串”與“A的前綴”能夠匹配的最大長度。
例:ababab
我們從“最大長度”6開始向下枚舉
若答案是6。根據定義,“A中以最后一個字符結尾的非前綴子串”是ababab?我們注意到,ababab也算它自身的一個前綴
因此,在枚舉時,要從這個字符串的長度減一開始枚舉!


若答案是5,則“非前綴子串”為babab。而“前綴”是ababa。兩者不相等。


若答案是4,則“非前綴子串”為abab,而“前綴”是abab。兩者相等。
所以我們可以確定,字符串”ababab”的“最長公共前后綴”長度為4。

有什么用?

舉例說明:有兩個字符串

S: abaacababcac
T: ababc
首先,根據最長公共前后綴,我們寫出T串的所有前綴的“最長公共前后綴”長度:
T[0~0] = “a”,最長公共前后綴長度:0
T[0~1] = “ab”,最長公共前后綴長度:0
T[0~2] = “aba”,最長公共前后綴長度:1
T[0~3] = “abab”,最長公共前后綴長度:2
T[0~4] = “ababc”,最長公共前后綴長度:0
我們把求得的這5個數記為X數組(因為它還不是next數組)

這個更改后的X數組就是next數組,下圖是上面的執行

next數組的含義是:當S[i]和T[j]不相等,並且j不等於-1時,j指針該指向的位置,且i指針不動。

當然我們目前只是枚舉,接下來如何用算法實現求next數組

求next數組

假設一個新的字符串
R:       a b c a b d e a b c a b c f
next:  -1 0 0 0 1 ?
我們要求next[5]

情況一 R[i-1] == R[next[i-1]]

比如R[5-1]=R[1],所以顯然next[6]=next[5]+1=2

 

 

 情況二 若R[i-1]!=R[next[i-1]]

R:       a b c a b d e a b c a b c f
next: -1 0 0 0 1 2 ?
我們發現R[i-1]和R[next[i-1]]並不相等。

用肉眼可以看出,我們在abcabd不管怎么取后綴,后綴的最后一個字符d,從來就沒有在前面出現過。所以它不可能和任何一個前綴相等。所以next[6]才是0。


假設我們求到了這種程度
R:       a b c a b d e a b c a b c f
next:  -1 0 0 0 1 2 0 0 1 2 3 4 5 ?
發現R[2] == ‘c’。換言之,枚舉next[13]時,我們發現6不行,5不行,4不行,其原因都在最后一個字符’c’不是前綴的最后一個字母。
剛才我們發現R[next[12]],也就是R[5],和這個最后一個字符是不一樣的
但是,R[next[5]] = R[2] = ‘c’就和R[12]是一樣的。也就是說,R[12] == R[next[next[12]]]。
這不是巧合。可以證明,只要找到了這個’c’,且next[next[12]]=2,則R[13]就是2+1=3。並且可以證明,除了next[12]+1,next[next[12]]+1,next[next[next[12]]]+1…以外,next[13]不會有其他的答案了。
只要多次迭代,就能求出next[13]。
經過多次迭代,如果發現迭代到了-1這里還沒有找到最后一個字符,那么我們直接讓next[13]=-1+1=0就可以了。這也是我們讓那個X[0]=-1的又一個原因。

總結

 

 

 這就是求整個next數組的詳細過程了,匹配的過程大家應該都懂,就不說了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM