意圖理解——KMP算法

想寫一個算法思路(意圖)的系列,從KMP算法開始吧,不講代碼,只講”爲什麼要這麼想,這麼寫“,看網上這麼講的還沒見到,自己想寫的還是必須自己寫啊~

KMP一直看書不明白的,看視頻真的有幫助,老師會自然而然地說出思路而非書上那般生硬。
B站,嚴蔚敏奶奶視頻教程


一、kmp的目標:

1,防止i指針回溯。

需要重新匹配時,其實前面的已經匹配成功,問題可以轉化爲模式串的自比較,從而省去i指針的回溯。

2,讓j指針回溯得儘量少。

模式串的前綴、後綴最長重複位數可以代表需要跳過幾位。


二、一個實例

一位一位比較時
遇到主串i指針的字符 與 模式串j指針的字符 不匹配時。

-------i
abaabcabbbbb
abaabcac
-------j

發生了i指針回溯,同時產生了已經成功匹配序列的錯位

-i
abaabcabbbbb
-abaabcac
-j

再一位一位比較……

--i
abaabcabbbbb
--abaabcac
--j
---i
abaabcabbbbb
--abaabcac
---j

突破點是已經成功匹配的字符串,錯位後,除了一些特殊情況,必然不能匹配!

那個“特殊情況”就是前綴與後綴的重複,同時,匹配成功的主串、模式串的部分是相等的! 這樣next數組僅僅交給模式串就等於主串、模式串都遵守了!
——回到第一步那裏,接着可以直接進行下一步:j回溯到模式串的b(從第一步的c)。

-------i
abaabcabbbbb
------abaabcac
-------j

三、原理要點

0,明白什麼不用比較,什麼還需比較
1,基於已經成功匹配的字符串(已知匹配成功的位數)
2,i回溯會導致已經匹配成功的串錯位(主串與模式串),如何防止i指針回溯導致的浪費?——除了一些特殊情況,錯位必然不能匹配!
3,特殊情況——只用考慮【已經匹配成功的部分主串(也就是部分模式串!匹配成功的部分代表它們完全一致!)】的錯位是否會有”重複“
4,錯位時,模式串前綴後綴的重複可以避免重新匹配(模式串與模式串——next數組)
5,next數組標記的有關於當前字符子串前綴、後綴最長重複長度,也就是可以不直接退回j串第一個字符的可以少回溯的重複部分。


四、理解next

教材定義圖引自:https://blog.csdn.net/qq_37969433/article/details/82947411
在這裏插入圖片描述
*注:教材上的”1“是[其他情況],不是[”不匹配時“]
這圖上的精確的數學語言看着就讓人頭疼,不如按着公式試試幾個例子。

這是嚴蔚敏教材P81的next數組值

abaabcac
01122312

驗證公式:我們取第4位的”a“,則這個a的next[4]的值是”k=2“,[1到2-1]=[4-2+1到4-1]即【1到1】=【3到3】即 [a]=[a]。
這也應當是”最長前後綴重複長度“

abaabcac
---2----

驗證公式:我們取第6位的”c“,則這個a的next[6]的值是”k=3“,[1到3-1]=[6-3+1到6-1]即【1到2】=【4到5】即[ab]=[ab]。
這也應當是”最長前後綴重複長度“

abaabcac
-----3--

下面是回溯j指針的實例。
【現在是f比a】同時,在匹配錯誤時跳過多少?

---i
abafbcabbbbb
abaabcac
---2----------------next

回溯至2【現在是f比b了】(j=next[j],就是j賦值當前位置的next數組的值,也就是下一步的位置(已經算好了跳到哪裏))

---i
abafbcabbbbb
--abaabcac
---1-----------------next

回溯至1(回溯到頭都沒有,之前的整串又配不上,GG,真匹配不上了)
這裏發現了又匹配到了f對a,這個涉及”對KMP算法的一種改進“,書上有。

---i
abafbcabbbbb
---abaabcac
---0------------------next

關於前綴後綴放張圖,下圖引自:https://www.cnblogs.com/zhangtianq/p/5839909.html
在這裏插入圖片描述

注意,next[j]內的值不代表j之前的子串前後綴的最大長度,而是“當模式串中第j個字符與主串相應字符‘失配’時,在模式串中需要重新和主串中該字符進行比較的字符的位置”。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章