動畫:用動畫給面試官解釋 KMP 算法,KMP 算法終於弄懂了

大家好,我是一個每天在互聯網都被讀者催更催到爆肝,爆腎小鹿童鞋。

在這裏插入圖片描述
說實話,一些數據結構和算法我這輩子都不可能用到實際當中,但個人一直覺得能把複雜的東西講明白是一件很牛逼的事情。

在這裏插入圖片描述
畢竟想牛逼也是很難的,並不是我說了算,前幾天更新的的 BF 和 RK 算法,就被後臺小夥伴的留言瘋狂石錘,哼!你牛逼你就講講 KMP 算法,我要石錘。

這幾天嚇得俺吃飯吃不消,睡覺睡不香,幹啥啥不行,這無數的與 KMP 戰鬥的夜晚。今天他來了,他帶着 KMP 來了。講就講,今天不講明白你們誰都別想走,放學都在學校門口等着。

在這裏插入圖片描述
(爲了能夠讓大部分讀者對 KMP 的基本原理,文中不具體分析代碼實現)


什麼是 KMP?

聽說 KMP 算法是一種字符串的改進算法,嗯~ 字符串匹配算法還有啥?不好意思,記性不好,居然忘記了。咱們繼續,KMP 算法是由D.E.Knuth,J.H.Morris 和 V.R.Pratt 發明的,至於名字怎麼讀,四級沒過,反正我不認識。

這都不重要,重要的是 KMP 算法的核心,它是主要利用匹配失敗後的信息,儘量減少模式串與主串的匹配次數以達到快速匹配的目的。

嗯~ 聽起來比暴力破解法牛逼的多,至於如果快速匹配的,還需要深入研究一下。


KMP的由來?

在一個夜黑風高的夜晚,我翻看了全網的 KMP ,讀了一遍又一遍,還是看不懂,不知吃了多少碗泡麪之後,突然靈感來了,

我快速打開編輯器,寫下了兩行測試字符。在這裏插入圖片描述

如果由以上模式串和子串,子串要在模式串中做一個字符串匹配,一般的匹配過程如下:

在這裏插入圖片描述

當我們遇到最後一個字符匹配 E 與 D 並不能完全匹配,那麼我們開始往後移動子串一個,一個個重新進行比較。
在這裏插入圖片描述

然而發現第一個字符就不能匹配成功,那好吧,繼續往後移動子串。

直到移動到下面這種情況,雖然匹配了 A 和 B,但是到了第三個字符,E 和 C 又不能匹配了,真傷心,好不容易匹配成功前兩個。

在這裏插入圖片描述

通過以上,我們發現暴力匹配,就算前幾個已經匹配成功,但是由於最後匹配失敗導致了重新移動一位,這也太浪費時間了。

既然我們知道前幾位匹配的信息。比如第一次匹配,我們知道了已經成功匹配了 ABCAB 了。能不能利用已經知道的匹配信息進行析,然後一次性往後移動多位呢?


KMP 原理

實話告訴你,沒有。但是這幾個人做到了,分別是 K 某,M 某,P某的三個人,不愧是大佬中的傳奇人物,我就咋沒想到呢?這次又被石錘智商低下了。

但是我們想象能力還是挺強的,假如有一個神奇的“表”,我們暫且起名叫做匹配表吧,那麼我們每次移動的次數,這個神奇的表能夠告訴我們,我們豈不是美滋滋的往後移動多位進行快速匹配不就可以了嗎?

尼瑪尼瑪哄,你罵誰呢?不好意思,錯了,重來,瑪尼瑪尼哄,這張神奇的匹配表說來就來。

在這裏插入圖片描述

雖然這個表目前是幻想出來的,無關緊要,我們再試着匹配一次上邊用到的字符串。

在這裏插入圖片描述

開始正式匹配,匹配到 E 和 D 就卡殼了,既然有了神奇的匹配表,不需要一個個的移動了,我們應該問一下神奇的“表”,魔錶魔錶,下一步應該把子串移動多少位?

在這裏插入圖片描述

此時匹配表進行瘋狂的計算,對於如何計算,也告訴我們公式了。它來詢問你,這才字符匹配成功匹配了幾個字符,很容易在圖中得到,ABCAB 共 5 位匹配成功。

然後又問,這五位中最後一位是誰?當然是 B 了,那麼 B 在匹配表中的匹配值是多少?稍等,我看看匹配表哈~ 嗯~ 這個 B 對應的是 1。

好了,用成功匹配的位數減去匹配值就是下一次要移動的次數。

納尼?這麼神奇?然後我就傻了吧唧相信了去試了試,測試過程如下。

在這裏插入圖片描述

嗯~ 5 - 2 等於 3,所以我要將子串移動四位,如下圖位置。

在這裏插入圖片描述

然後我再進行匹配,當遇到 E 與 C 的時候,匹配失敗,此時已經匹配了兩個元素,分別爲 AB,那下一次要往後移動多少呢?

在這裏插入圖片描述
還是按照上邊的方式計算,已匹配 2 的字符,此時已匹配字符 AB 最後一個字符是 B,所以這個 B 對應的匹配表的匹配值爲0,往後移動 2-0等於 2,往後移動兩位。

在這裏插入圖片描述

繼續匹配,發現第一個字符就匹配失敗了,繼續移動一位,最後發現全匹配。

在這裏插入圖片描述

整體的 KMP 算法就是這麼一個思路,但是我們所用到的這個匹配表示我們想象出來的,能不能計算出來呢?理想總是很美好,但現實很骨感。

在這裏插入圖片描述

計算匹配表

首先要弄懂兩個概念,就是前綴和後綴的概念。

對於我們的子串來說,它的前綴有哪些呢?對於前綴就是除了最後個字符以外所有的順序組合方式。比如 A、AB、ABC、ABCA、ABCAB。

後綴正好相反,除了第一個字符外,其他所有的組合方式。比如BCABD、CABD、ABD、ABD、BD、D。

在這裏插入圖片描述

對於每個匹配值是如何計算的,那就對子串的每個字符組合尋找出前綴和後綴,然後進行比較是否有相同的,相同的字符組合有幾位,就是所謂的匹配值。

這樣純文字說可能很懵逼,直接上圖。

在這裏插入圖片描述

我們可以在圖中發現,並沒有對子串移動的規律發現任何問題,但是我們在看一下子串。

在這裏插入圖片描述

突然恍然大悟,從上圖中發現有時候在同一字符串中出現兩種相同的字符,比如上圖中的 AB,由兩個字符組成的,所以匹配值爲 2,同時在匹配的過程中,如果 D 前邊的字符能夠匹配,則子串往後移動 3 位,則再次匹配 AB,原來這是 KMP 的精髓所在。


❤️ 不要忘記留下你學習的腳印 [點贊 + 收藏 + 評論]

文章整理了好幾個小時,不妨點贊支持一下。嘻嘻,你不點贊說明你很自私,你怕那麼好的文章讓別人也看到。開個小小玩笑。

1、老鐵們,關注我的原創微信公衆號「小鹿動畫學編程」,專注於數據結構與算法、網絡原理、Web 大前端。

2、給俺點個讚唄,可以讓更多的人看到這篇文章,順便激勵下我,嘻嘻。

在這裏插入圖片描述

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