文章的一開頭,仍是要強調下字符串匹配的思路:html
將模式串
和主串
進行比較算法
主串
和模式串
的下一個位置失配時,segmentfault
在模式串
中尋找一個合適的位置數組
主串
當前失配位置進行比較模式串
的頭部與主串
失配位置的下一個位置進行比較主串
中找到一個合適的位置,從新與模式串
進行比較前面的 BF
和 KMP
算法,都是屬於規規矩矩從前向後的操做,後者僅在尋找模式串
的合適位置上進行了優化,而 BM
算法的操做就顯得騷了不少,它的優化點在於:數據結構
主串
中合適的位置關於算法的介紹和分析,網上有不少解釋,這裏推薦一下阮一峯的字符串匹配的Boyer-Moore算法,很清楚的講解了整個優化的思路,能夠先看完理解了再往下看,由於下面主要介紹一下壞字符規則
和好後綴規則
須要的數據結構的手工求法以及代碼實現。框架
運用壞字符規則,在算法裏主要體如今生成一張散列表,表的key值是字符集裏每一個字符的ASCII碼值,value值是模式串中該字符的位置,舉個栗子:函數
假設字符串的字符集不是很大,用長度爲256
的數組來存儲,而且初值賦值爲-1
。數組的下標對應字符的 ASCII
碼值,數組中存儲這個字符在模式串中出現的位置。這裏要特別說明一點,若是壞字符在模式串裏多處出現,選擇最靠後的那個,由於這樣不會讓模式串滑動過多,致使原本可能匹配的狀況被滑動略過。優化
好後綴規則體如今如何求出 suffix
和 prefix
兩個數組以及移動規則
。spa
key值表示的是後綴子串的長度,value值表示的是在模式串
中跟好後綴 S 相匹配的最後一個子串 S' 的首字母在模式串
中的key值,以下圖:3d
一樣的,key值表示的是後綴子串的長度,而value值表示的是模式串
中,是否有和該長度下後綴子串相同的前綴子串,是的話爲 true
,不然爲 false
,以下圖:
移動規則總結以下:
在模式串
中尋找跟好後綴 S 相匹配的最後一個子串 S'
模式串
移動到使得 S' 和主串
對齊的位置模式串
的前綴子串
中是否有和 好後綴 S
的後綴子串
匹配的位置,滑動模式串
以對齊。模式串
移動至主串
與模式串
末尾對齊的下一個位置下圖分別對應三種狀況:
參考字符串匹配的思路
主串
和模式串
的字符對比,因此須要兩個指針 i
,j
分別指向主串
和模式串
,記錄位置 須要一個循環來重複進行匹配操做,此時思考終止條件:
i
指向主串
每次匹配的合適位置,從前日後掃描;j
指向模式串
的尾部,從後往前掃描。考慮極端狀況:主串
和模式串
對比完,仍然沒法匹配。此時,i
的位置必定小於等於 主串
長度 n
與模式串
長度 m
的差值。具體可看下圖。模式串
從後往前與主串
進行匹配,這也須要一個內層循環來驅動指針j
壞字符規則
和好後綴規則
計算出 i
須要移動的位置,選擇兩個值當中最大的,從新計算 i
的值,重複進行匹配。
根據以上分析能夠寫出整個的邏輯框架代碼:
框架寫好後,接下來就是完善三個輔助函數便可
這個就沒有什麼能夠多說的了,只要參考上面分析的,一步一步寫出代便可:
suffix
和 prefix
拿下標從 0
到 i
的子串(i
能夠是 0
到 m-2
)與整個模式串,求公共後綴子串。若是公共後綴子串的長度是 k
,那就記錄 suffix[k]=j
(j
表示公共後綴子串的起始下標)。若是 j 等於 0
,也就是說,公共後綴子串也是模式串的前綴子串,就記錄 prefix[k]=true
。能夠本身動下手,模擬下代碼的運行,尤爲注意中k
值的運用,很巧妙。
根據上面此步的算法分析,也能夠寫出:
總的來講,BM算法
另闢蹊徑,經過從後往前的匹配的思路,加上壞字符規則和好後綴規則來優化移動的步數,從而提升算法的匹配效率。
「字符串匹配算法」是「重學數據結構與算法」系列筆記: