数据结构与算法 / 字符串匹配 / BF、PK 算法
零、前言
為了下面便于說明,先定義兩個名詞,分別是主串和模式串。在字符串 A 中查找字符串 B,則 A 為主串,B 為模式串。
假設,主串中字符數量為 L1,模式串的字符數量為 L2 。
一、BF 算法
1、基本信息
BF 算法中的 BF 是 Brute Force 的縮寫,中文叫作暴力匹配算法,也叫樸素匹配算法。
2、查找流程
從主串第一個位置開始匹配模式串,匹配完成之后,模式串移動一個字符,移動次數為 L1 - L2 + 1 次完成對主串的匹配。
上述過程中可以的優化的點是每次匹配時發現一個字符不一樣時就可以中斷當前匹配過程直接進入下一個匹配。
3、時間復雜度
單次匹配的次數為 L2,一共 匹配 L1 - L2 + 1,故時間復雜度為 O(L1*L2),即:O(n*m) 。
二、PK 算法
1、基本信息
RK 算法的全稱叫 Rabin-Karp 算法,是由它的兩位發明者 Rabin 和 Karp 的名字來命名的。
該算法可以理解為 BF 算法的升級版。
設計思路大概為: BF 算法簡單但是時間復雜度高,為了解決該問題,可以優化的地方是更改每次匹配時比對的內容,由之前的比對每一個字符改為比對雙方的 hash 值,進一步優化 hash 值計算的方法從而降低查找的時間復雜度。
2、查找流程
(1)version 1
將主串拆分成(L1 - L2 + 1)個子串,計算每一個子串的 hash 值;計算模式串的 hash 值。最后用模式串 hash 值與主串的(L1 - L2 + 1)個子串的 hash 值進行對比,相同的即為字符串匹配。
(2)version 2
在版本 1 的思路下繼續延伸,計算 hash 值時間依然較多,此處可以優化。可以將 26 個英文字母作為 0、1、2、3、……、25 數字,將字符串轉成十進制數字,栗子:
字符串:gced,轉換成數字:6 * 26 ^ 3 + 2 * 26 ^ 2 + 4 * 26 ^ 1 + 3 * 26 ^ 0 = 106915 ,暫稱該數為神秘數。
上述每一個主串的子串以及模式串均計算出神秘數,對比神秘數即可完成字符串匹配。當然有?神秘數 沖突的情況,每次神秘數比對相同時可以再次對比下兩個字符串。
(3)version 3
在版本 2 中,每次計算神秘數的過程依然可以優化,如下所示:
假設主串為 gcedb
字符串:gced,轉換成數字:6 * 26 ^ 3 + 2 * 26 ^ 2 + 4 * 26 ^ 1 + 3 * 26 ^ 0
向后挪一位,得到字符串 cedb,轉換成數字:2 * 26 ^ 3 + 4 * 26 ^ 2 + 3 * 26 ^ 1 + 1 * 26 ^ 0,
可以發現計算 cedb 的神秘數時,可以寫成如下:26*(2 * 26 ^ 2 + 4 * 26 ^ 1 + 3 * 26 ^ 0) + 1 * 26 ^ 0,括號部分的值已經在計算?gced 神秘數的時候得到了,這樣每次保存上一個神秘數的一部分計算結果省略了大量的計算過程,可以降低時間復雜度。
3、時間復雜度
一共 匹配 L1 - L2 + 1,故時間復雜度為 O(L1),即:O(n) 。
4、神秘數沖突
當神秘數沖突過多時,實際上 PK 算法就退化成了 BF 算法,因為要頻繁的比對子串和模式串,加大的時間復雜度,所以如何計算神秘數是關鍵,上述的計算過程僅僅是其中之一的方法。
?
參考:極客時間《數據結構與算法之美》王爭
這門課真心推薦,內容很經典、栗子很形象,里面還包含了很多面試題目。真是居家旅行必備良藥。
(SAW:Game Over!)
總結
以上是生活随笔為你收集整理的数据结构与算法 / 字符串匹配 / BF、PK 算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构与算法 / 堆结构
- 下一篇: 数据结构与算法 / LRU 缓存淘汰算法