如果要判定長度為n
nn兩個字串相等,比較中要進行n
nn比較,但是如果要判定兩個字串不相等,只需要找出乙個不相等的位置,因此可以得到如下結論:
結論1:判定字串相等和判定字串不相等的代價不同,判定不相等的代價更小
在kmp演算法中,每發生一次失配時,演算法總是嘗試根據已經獲得的匹配成功的資訊來確定乙個新的對齊位置,也即kmp演算法是在嘗試判斷兩個字串相等,根據結論1,這種做法的代價要大於判定字串不相等的代價。因此bm演算法是嘗試判定兩個字串不相等。
如果區域性匹配成功,對於文字串p
pp和區域性的模式串par
ttpartt
part
t,我們有如下結論:
結論2:
( p=
part
t)⟹(
∀p∈p
,∀t∈
part
t⟹p=
t)(p = partt)\longrightarrow (\forall p\in p,\forall t\in partt \longrightarrow p = t )
(p=par
tt)⟹
(∀p∈
p,∀t
∈par
tt⟹p
=t)因此文字串p
pp和區域性的模式串par
ttpartt
part
t對應位置字元相等是匹配成功的乙個必要條件,根據這個必要條件我們可以得到bm演算法的樸素思想。
以下面插圖為例:
文字串t
tt和模式串p
1p_1
p1進行匹配時,文字串中的字元x和模式串中的字元y失配,此時需要重新選定匹配位置。觀察模式串發現,在字元y的前面,存在乙個字元x,此時可以將綠色的x和紅色的x對齊,然後再從頭開始對比。
當模式串為p
2p_2
p2時,失配之後發現在字元y的前面沒有字元x,這說明了無論這部分進行怎樣的區域性匹配,最終都不可能匹配成功。因此可以直接跨過文字串字元x以前的位置。
結論3:失配的位置越靠後,能夠排除的對齊位置越多
因此bm演算法不同於kmp演算法,它的每次比對是逆向進行的。
**只要我們記錄下每個字元在模式串中的位置,當匹配失敗時,找到乙個新的位置進行比對即可,為此我們構造乙個bc[ ]陣列。
考慮兩種邊界情況:
第一種情況我們只需要令bc[
′x′]
=−1bc['x'] = -1
bc[′x′
]=−1
即可,也就是使用通配哨兵。
第二種情況如果不特殊處理,會使模式串往回移動,出現該種情況使,我們只需要令模式串前進乙個單位即可。
演算法分為兩個部分:構造bc[ ]陣列和串匹配。
//構造bc
int*
buildbc
(const string &s)
//串匹配
intbc
(const string &s1,
const string &s2)
if(j <0)
break
;int d =
max(
1, j - bc[s1[i + j]])
; i +
= d;
}return i;
}
BM演算法詳解
bm演算法 字尾匹配,是指模式串的比較從右到左,模式串的移動也是從左到右的匹配過程,經典的bm演算法其實是對字尾蠻力匹配演算法的改進。為了實現更快移動模式串,bm演算法定義了兩個規則,好字尾規則和壞字元規則,如下圖可以清晰的看出他們的含義。利用好字尾和壞字元可以大大加快模式串的移動距離,不是簡單的 ...
BM演算法總結
bm演算法,可以求乙個數列的最短遞推式。採用增量法,依次考慮每個數 若在這個位置上正確,則忽略 否則,類似拉格朗日插值法,找乙個滿足在前面位置都為0,這個位置上不為0的遞推式,進行修補。每當我們遇到乙個這樣的位置時,我們都可以得到乙個這樣的遞推式 用目前的遞推式,在0位置 即這個位置上 增加乙個 1...
BM演算法(筆記)
利用多位移動減少不必要的匹配。兩條字串 主串,匹配串 主串不動,匹配串去匹配 以下是匹配串針對主串而言 初始位置 最左對齊 匹配方向 從右向左 即初始位置對齊後,從匹配串最後乙個字元開始匹配 移動方向 從左向右 從右向左匹配時,出現不匹配的字元稱為 壞字元 壞字元有兩種情形,分別是 匹配串存在該壞字...