遞歸思想與KMP算法

遞歸思想與KMP算法

很有幸讀到了很實用優秀的一篇關於kmp算法的解釋博客通俗易懂的字符串匹配KMP算法及求next值算法,在寫博客前推薦給大家。
接下來是我自己對遞歸相關知識的理解和總結

迭代和遞歸
迭代是適合對數據掌握很多的,知道有幾層。遞歸是適合掌握很少信息的。現實問題中能用迭代就不要用遞歸,因爲效率很低。迭代時循環結構,而遞歸是選擇結構。

斐波那契數列的遞歸實現
以兔子的繁衍爲例:
在這裏插入圖片描述
遞歸定義:一個直接調用自己或者間接調用自己的函數,叫做遞歸函數。每一個遞歸必須至少有一個條件,當滿足這個條件時,遞歸結束,不然就會陷入永無止盡的循環遞歸。

遞歸可以使程序結構更清晰,減少讀懂程序的時間。但是大量的遞歸會建立很多副本,很消耗內存和時間

遞歸有調用和回退兩個階段,回退是調用的逆序。遞歸是一個過程,每一次調用過程都是一樣的。如:算n!

分治思想:把問題分解成一個個小模塊,每個模塊都是類似的問題,然後一個個解決每個模塊的問題。

實際應用
漢諾塔 藉助中間的柱子實現
八皇后問題每次都是尋找安全區域的新皇后,在下一個安全區域再尋找新皇后

字符串
串string:零個或者多個字符組成的有限序列。字串和主串,over是lover的字串。
字符串的比較大小:字符串裏每一個字符的ASCII碼的大小
字符串的存儲結構:順序和鏈式。因爲不同的字符串一般是連在一起表述的,不能斷章取義,所以我們習慣用順序,定義一段足夠長的存儲去來存儲。

BF算法和KMP算法
BF:樸素的模式匹配算法。從開頭一個一個匹配。很暴力但是效率低下。
KMP
直接上圖
在這裏插入圖片描述
第0號元素存放字符串的長度,所以1表示第一個元素。我們發現,i5不等於j5。就會回溯到下圖位置
在這裏插入圖片描述
回溯法思維:在哪裏跌倒就從哪裏爬起來,思想好效率低。
KMP思維:省去不必要的回溯,問題應該由模式串(下面那一串)決定,而不是目標串。
在這裏插入圖片描述
這裏有S和T串,同樣在i5出現失配。需要回溯得是j,而i是不需要的。所以直接用j1, 回溯到1,對應到失配的地方i5,重新開始匹配
在這裏插入圖片描述
接下來是特殊情況
情況一
在這裏插入圖片描述
因爲i1=i2,在i3失配,則j只需要回溯到2

情況二
在這裏插入圖片描述
因爲 i1,i2=i4,i5 j1,j2=i1.i2 所以 j1,j2=i4,i5
爲了不錯過任何有可能的匹配,j需要回溯到2的後一位,和失配處匹配

情況三
在這裏插入圖片描述
j 向右移一個,因爲不知道之後會有什麼。

基於以上情況的總結:
如果前面無重複,j從1開始回溯
如果前面沒重複,T串1個一樣,j從2開始回溯,T串2個一樣,j從3開始回溯,T串有3個相等,j從4開始。

next數組
現在給模式匹配串 T串 添加一個k數組,也就是next數組。用來指導模式匹配串下一步應該改用第幾號元素去匹配。
還是那幾個列子動圖演示視頻
重點搞清楚什麼是前綴和後綴
前綴就是第一個元素往後,後綴司最後一個元素往前,有重複元素時應該特殊處理,舉例:
S abaaabb
T abaaaba *此處失配,前綴爲ab,後綴也是ab,有2個重複,k=3

S abaaabb
T ababbaa*此處失配,前綴是a,後綴也是a,有1個重複,k=2

S abaaabb
T abcabcb*此處失配,前綴是a,後綴是b,沒有重複,k=1

S ssssst
T sssstt*此處失配,前綴爲sss,後綴也是sss,有3個重複,k=4

應試捷徑
現在我們發現一個問題:
我們不用去管目標串 S串 具體有哪一些元素,要判斷k的值,只需要看模式串 T串 在失配項之前的元素有多少是重複的就可以了,代碼只需要知道下一步要走到哪裏。

KMP代碼實現教學後綴是相對的,前綴是固定的

KMP是有缺陷的,比如:
S aaaabce
T aaaax
很容易得到next是 01234
但是元素在第四個a處失配,沒有必要回溯到123,效率很低。
改進:如果T失配元素和T前綴元素相等,那就應該回溯到前綴元素的next值上面去,因爲中間的那一段都是相等的,就直接回到前綴元素,他的next值什麼就指向下一個對應的j。
KMP並不是最優秀的字符串匹配算法

發佈了27 篇原創文章 · 獲贊 0 · 訪問量 485
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章