KMP算法的next/nextval值的個人理解


KMP算法的next/nextval值的個人理解

本文於2020.3.30.23:48重新編輯,之前看過的朋友們,你們看到並非完全正確的方法,非常抱歉!如果再次點開這篇博客,還請您重新閱讀一次,感謝!

之前學習KMP算法的時候對於next/nextval值的計算總是處在似懂非懂的狀態,后面結合了老師的方法和網上的資料自己總結了一下,下面是我自己的一些個人經驗,比較淺顯易懂,希望能幫到一部分人。

KMP算法的運行模式

KMP算法與BF算法的最大區別就是,BF算法每次匹配時模式串都是往下一位移動,又重新從模式串的第一位開始比對;而KMP算法的思想是,如果已有一部分字段匹配成功,在這一部分字段中尋找相同的兩部分小字段,即概念中的子串,以減少比較次數,提升算法效率。

但是,

這兩部分相同的子串,是有約束條件的。

計算next與nextval值

我們以串測試中的第7題為例,以下方法計算得的next與nextval值均遵循考試規則,可能不同教材有所不同。

注意:務必看完整個過程,切勿心急

在我們計算之前,要先知道next值的作用是什么。
實際上主串第i個字符與模式串某個字符不匹配后,有兩種不同的情況處理:
1.下次比較拿主串第i+1個字符與模式串第1個字符匹配;
2.下次比較依舊拿主串第i個字符與模式串的某個字符比較。
而next值的使用場景為:在KMP算法中,當主串與模式串逐個字符比較時,某個字符不匹配時,則模式串向右移動,移動的位數為next值+1。

首先next[0]的值固定為-1,而next[1]的值固定為0(關於這點后面會有解釋)

從第j=2開始,看前面的字段有無兩段相同的子串。此時前面字段為底色黃色的ab字段(以下情況的前面字段均以黃底標出)

很明顯沒有相同字段,故next[2]的值為0。這也能解釋為什么t[1]的next值一定為0,畢竟t[1]前僅有t[0]一個數,根本不可能存在兩段相同的子串,所以t[1]的next值必定為0。

j=3時同樣在前面字段中沒有兩段相同字段,不再贅述。

當j=4時,如下圖

可以看出前面字段abca中有兩段相同的子串a,用紅字標出,故相同字段的長度為1,則next值為1。(以下相同字段均以紅字標出)

繼續向下,當j=5時,情況與j=4相同。

當j=6時,如下圖

可以看出此時前面字段中相同子串為ab,故相同字段長度為2,next值為2

接下來,當j=7時

可以看出此時前面字段中沒有相同子串,故相同字段長度為0,next值為0但是,有些朋友看到這里會說,如果單純找前面字段中的相同子串,那像剛剛j=6時的ab字段在這里也符合標准,為什么next值不為2呢?或者,像下面這張圖片一樣,為什么next值也不是1呢?

前綴子串和后綴子串

還記得上文提到的有約束條件子串嗎?
這便是前綴子串后綴子串
前面的子串,叫前綴子串;同理,后面的子串,叫后綴子串

但關鍵在於,約束條件是什么呢?

讓我們再觀察一下剛剛那些沒有問題子串,也就是前綴子串后綴子串

上面兩張圖中前綴子串和后綴子串有什么共同點呢?

可以發現,前綴子串第一位均為t[0]
若將此時j的值設為x后綴子串最后一位均為t[x-1]
用圖形來理解,就是在黃底區域中,前綴子串的第一位必須是黃底區域的第一位,即t[0]
同樣的,后綴子串的最后一位必須是黃底區域的最后一位,即t[x-1]

讓我們回到j=7的情況中,在了解了前綴子串與后綴子串的定義之后,現在的你理解為什么next[7]=0了嗎?

如果你理解了,那么恭喜你,真正掌握了next值的求算方法

觀察模式串中的前綴子串和后綴子串,判斷出的next值就是准確的。多加練習,就能很快求出next值。下面是完整的表圖,大家可以對照着再練習一遍。

nextval值的求解

當你對next值的求解駕輕就熟之后,nextval值的求解相比之下就簡單很多,除了nextval[0]的值仍為-1,其他nextval值都遵循以下規則

不同則同,同則等於

這是什么意思呢?

下面是題7的nextval值表

注意:上表為正確的表,下面例子中的表格中的j=7一欄中的next及nextval值錯誤,請以上圖為准練習

我已經標出了所有數的nextval值,接下來讓我們看幾個例子:

當j=1時

t[1]=b,next[1]=0,則我們根據next[1]=0找到t[0]=a,a與b不同,則nextval[1]=next[1]=0,這就是不同則同

當j=2時

t[2]=c,next[2]=0,則我們根據next[2]=0找到t[0]=a,a與c不同,則nextval[2]=next[2]=0

當j=3時

t[3]=a,next[3]=0,則我們根據next[3]=0找到t[0]=a,a與a相同,則nextval[3]=nextval[0]=-1,這就是同則相等,即兩字符相同時兩者的nextval值相等

接下來的nextval值判斷同樣遵循以上方法,大家可以自己試着練習一下

注意:第一個表為正確的表,例子中的表格中的j=7一欄中的next及nextval值錯誤,請以第一個圖為准練習

使用上面的方法可以比較容易地得到next值與nextval值,希望可以幫助到大家的計算以及對KMP算法的理解。


免責聲明!

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



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