比KMP高效的Boyer-Moore字符串匹配算法

       在這裏我所要想說的比KMP算法高效的算法是Boyer-Moore算法。

       在講解Boyer-moore算法之前,在這裏先回顧一下KMP算法。

       比如說有一個字符串"BBC ABCDAB ABCDABCDABDE",我想知道,裏面是否包含另一個字符串"ABCDABD"。大部分情況下我們會使用KMP算法去解:

  1.                           

首先,字符串"BBC ABCDAB ABCDABCDABDE"的第一個字符與搜索詞"ABCDABD"的第一個字符,進行比較。因爲B與A不匹配,所以搜索詞後移一位。
2.

B與A不匹配,搜索詞向後移一位。直到有一位搜索詞相同。
3.


可以看到前6個數都是相同的,但是最後一個數D與空格不相同。根據KMP算法,搜索詞向後移動一位。但是這就是KMP算法效率低的地方,之前的6個數我們已經比較過了,已經不可能匹配了,但是KMP算法還是重複的匹配。在後面講的Boyer-Moore算法會有優化。
4.

     其實KMP在這裏是有優化的,KMP算法的想法是,設法利用這個已知信息,不要把"搜索位置"移回已經比較過的位置,繼續把它向後移,這樣就提高了效率。
    利用《部分匹配表》(Partial Match Table)可以根據公式:
             移動位數 = 已匹配的字符數 - 對應的部分匹配值;
 算出向後移動的位數。


5. 部分匹配表實例:

     "部分匹配"的實質是,有時候,字符串頭部和尾部會有重複。比如,"ABCDAB"之中有兩個"AB",那麼它的"部分匹配值"就是2("AB"的長度)。搜索詞移動的時候,第一個"AB"向後移動4位(字符串長度-部分匹配值),就可以來到第二個"AB"的位置。

Boyer-Moore算法:

壞字符算法:
           其實Boyer-Moore算法使用最多的是大部分軟件裏的“查找算法”。crtl+F4的功能。


注意:Boyer-Moore算法是從後向前匹配的。這是一個很聰明的想法,因爲如果尾部字符不匹配,那麼只要一次比較,就可以知道前7個字符(整體上)肯定不是要找的結果。

如上面的情況:
Boyer-Moore是怎麼處理的呢?

我們看到,"C"與"D"不匹配。這時,"C"就被稱爲"壞字符"(bad character),即不匹配的字符。我們還發現,"C"包含在搜索詞"ABCDABD"之中,這意味着可以把搜索詞直接移到"C"的後一位。


我們看到,"D"與"空格不匹配。這時,空格就被稱爲"壞字符"(bad character),即不匹配的字符。我們還發現,空格不包含在搜索詞"ABCDABD"之中,這意味着可以把搜索詞直接移到空格的後一位。


而後面的“C”和“D”不相同,但是我們可以注意到壞字符“C”在搜索詞“ABCDABD”中,根據規則我們將搜索詞中的“C”移動到壞字符處:


這樣,我們就找到了匹配的字符串了。。

我們可以總結Boyer-Moore的壞字符算法:

後移位數 = 壞字符的位置 - 搜索詞中的上一次出現位置

即:壞字符“C”(上面的那一個C)出現在搜索詞的第6位(從0開始),在搜索詞中上一次出現的位置是2。所以6-2=4。

向後移動4位。

注意:如果"壞字符"不包含在搜索詞之中,則上一次出現位置爲 -1。


Boyer-Moore算法除了有”壞字符算法“還有

”好後綴算法“:


   那麼好後綴算法是什麼樣的情況呢?這裏,我們得換個例子:
   如果出現這種情況:

    "MPLE"與"MPLE"匹配。我們把這種情況稱爲"好後綴"(good suffix),即所有尾部匹配的字符串。注意,"MPLE"、"PLE"、"LE"、"E"都是好後綴。

      比較"I"與"A"不匹配,那麼"I"就是壞字符。根據"壞字符規則",此時搜索詞應該後移 2 - (-1)= 3 位。但是在這裏我們採用"好後綴算法":
後移位數 = 好後綴的位置 - 搜索詞中的上一次出現位置
此時,所有的"好後綴"(MPLE、PLE、LE、E)之中,只有"E"在"EXAMPLE"還出現在頭部,所以後移 6 - 0 = 6位。


"壞字符規則"只能移3位,"好後綴規則"可以移6位。所以,Boyer-Moore算法的基本思想是,每次後移這兩個規則之中的較大值。

繼續從尾部開始比較,"P"與"E"不匹配,因此"P"是"壞字符"。根據"壞字符規則",後移 6 - 4 = 2位。

匹配完成。。。


     

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