單模式匹配算法,也就是一個字符串和另外一個字符串進行匹配。算法
BF 算法中的 BF 是 Brute Force 的縮寫,中文叫做暴力匹配算法,也加樸素匹配算法。從名字能夠看出,這種方法很暴力,效率也不高,可是簡單、好懂。數組
在要匹配的兩個字符串中,一個稱之爲主串,一個稱之爲模式串。好比要在字符串中 A 中查找字符串 B,那麼字符串 A 就是主串,字符串 B 就是模式串。子串的長度爲 n,模式串的長度爲 m,由於要在主串中查找模式串,因此有 n>m。數據結構
BF 算法的思想很簡單,就是拿主串中起始位置分別爲 長度爲 m 的總共 n-m+1 個子串分別與模式串進行比較,看有沒有能匹配上的。函數
能夠看到,每次咱們都要比較 m 個字符,極端狀況下總共要比較 n-m+1 次,因此算法的最壞狀況時間複雜度爲 O(m*n)。.net
能夠看到,這個算法的時間複雜度很高,但在實際的開發中,它倒是一個比較經常使用的字符串匹配算法。一者由於實際開發中兩個字符串的長度都不會太長,並且也不會每次都須要比較 n-m+1 次;兩者由於其算法實現起來很是簡單,不容易出錯,便於維護。這也就是咱們常說的 KISS(Keep it Simple and Stupid) 原則。設計
RK 算法的全稱叫做 Rabin-Karp 算法,是爲了記念它的兩個發明者而這樣命名的。 這個算法其實就是剛剛 BF 算法的升級版。3d
在 BF 算法中,每次都要對 m 個字符逐個進行比較,這就大大下降了算法的效率。這時候,咱們引入哈希算法,對子串逐個求哈希值,而後與模式串的哈希值進行比較來判斷兩個子串是否匹配。在不考慮哈希衝突的狀況下,數字之間的比較就很是快了。cdn
可是,在計算子串哈希值的時候,咱們依然須要遍歷 m 個字符,算法總體的效率並無提升。咱們須要設計一個特殊的哈希函數來避免每次都要遍歷 m 個字符,這樣,算法的效率就會大大改善。blog
對此,咱們將包含 K 個字符的子串用一個 K 進制數來表示,將這個 K 進制數轉化爲 10 進制數做爲子串的哈希值。好比字符串都是由小寫字母組成,那麼 a-z 這 26 個字母就映射到 0-25,0 表示 a,1 表示 b,以此類推。將 K 進制的數轉化爲 10 進制只須要將 10 變爲 K 便可,以下圖所示。開發
這樣計算哈希值的話相鄰兩個子串就有必定關係。
假設 、 分別是起始位置爲 和 的哈希值,而 爲位置爲 處字符的的映射,那麼就有:
其中 這個指數項能夠事先計算出來放在一個數組中,當咱們須要的時候,就從對應下標中取出來便可。
能夠看到,計算哈希值的時候,咱們只須要遍歷一次主串便可計算出全部子串的哈希值,這部分時間複雜度爲 O(n)。模式串和子串須要比較 n-m+1 次哈希值,這部分時間複雜度也爲 O(n)。因此,RK 算法總的時間複雜度爲 O(n)。
可是,若是模式串的長度很大,那麼計算出來的哈希值就會超出計算機中整形數據能夠表示的範圍。這時候,咱們就能夠犧牲一下,容許出現哈希衝突,好比能夠求全部字符的映射和等,這種狀況下哈希值的範圍就小不少了。此時,當兩個子串哈希值相同時,咱們須要再進一步肯定兩者自己是不是相同的。
獲取更多精彩,請關注「seniusen」!