bm演算法
字尾匹配,是指模式串的比較從右到左,模式串的移動也是從左到右的匹配過程,經典的bm演算法其實是對字尾蠻力匹配演算法的改進。
為了實現更快移動模式串,bm演算法定義了兩個規則,好字尾規則和壞字元規則,如下圖可以清晰的看出他們的含義。利用好字尾和壞字元可以大大加快模式串的移動距離,不是簡單的++j,而是j+=max (shift(好字尾), shift(壞字元))
先來看如何根據壞字元來移動模式串,shift(壞字元)分為兩種情況:
此處配的圖是不準確的,因為顯然加粗的那個b並不是」最 靠右的」b。而且也與下面給出的**衝突!我看了**,**的意思是最右邊的。當然了,儘管一時大意圖配錯了,論述還是沒有問題的,我們可以把圖改正一 下,把圈圈中的b改為字母f就好了。接下來的圖就不再更改了,大家心裡有數就好。
為了用**來描述上述的兩種情況,設計乙個陣列bmbc['k'],表示壞字元『k』在模式串中出現的位置距離模式串末尾的最大長度,那麼當遇到壞字元的時候,模式串可以移動距離為: shift(壞字元) = bmbc[t[i]]-(m-1-i)。如下圖:
陣列bmbc的建立非常簡單,直接貼出**如下:
1 void prebmbc(char *x, int m, intbmbc)**分析:
再來看如何根據好字尾規則移動模式串,shift(好字尾)分為三種情況:
為了實現好字尾規則,需要定義乙個陣列suffix,其中suffix[i] = s 表示以i為邊界,與模式串字尾匹配的最大長度,如下圖所示,用公式可以描述:滿足p[i-s, i] == p[m-s, m]的最大長度s。
構建suffix陣列的**如下:
1 void suffixes(char *x, int m, int *suff) 2 10 }·註解:這一部分**乏善可陳,都是常規**,這裡就不多說了。
有了suffix陣列,就可以定義bmgs陣列,bmgs[i] 表示遇到好字尾時,模式串應該移動的距離,其中i表示好字尾前面乙個字元的位置(也就是壞字元的位置),構建bmgs陣列分為三種情況,分別對應上述的移動模式串的三種情況
構建bmgs陣列的**如下:
1 void prebmgs(char *x, int m, intbmgs)註解:這一部分**挺有講究,寫的很巧妙,這裡談談我的理解。講解**時候是分為三種情況來說明的,其實第二種和第三種可以合併,因為第三種情況相當於與好字尾匹配的最長字首長度為0。由於我們的目的是獲得精確的bmgs[i],故而若乙個 字元同時符合上述三種情況中的幾種,那麼我們選取最小的bmgs[i]。比如當模式傳中既有子串可以匹配上好後串,又有字首可以匹配好後串的後串,那麼此 時我們應該按照前者來移動模式串,也就是bmgs[i]較小的那種情況。故而每次修改bmgs[i]都應該使其變小,記住這一點,很重要!而在這三種情況中第三種情況獲得的bmgs[i]值大於第二種大於第一種。故而寫**的時候我們先計算第三種情況,再計算第二種情況,再計算第一種情況。為什麼呢,因為對於同乙個位置的多次修改只會使得bmgs[i]越來越小。
1. 為什麼從後往前,也就是i從大到小?原因在於如果i,j(i>j)位置同時滿足第二種情況,那麼m-1-i
2. 第8行**的意思是找到了合適的位置,為什麼這麼說呢?因為根據suff的定義,我們知道x[i+1-suff[i]…i]==x[m-1-siff[i]…m-1],而suff[i]==i+1,我們知道x[i+1-suff[i]…i]=x[0,i],也就是字首,滿足第二種情況。
3. 第9-11行就是在對滿足第二種情況下的賦值了。第十行確保了每個位置最多只能被修改一次。
再來重寫一遍bm演算法:
1 void bm(char *x, int m, char *y, intn) 16 else 17 j += max(bmgs[i], bmbc[y[i + j]] - m + 1 +i); 18 } 19 }
演算法 BM演算法
如果要判定長度為n nn兩個字串相等,比較中要進行n nn比較,但是如果要判定兩個字串不相等,只需要找出乙個不相等的位置,因此可以得到如下結論 結論1 判定字串相等和判定字串不相等的代價不同,判定不相等的代價更小 在kmp演算法中,每發生一次失配時,演算法總是嘗試根據已經獲得的匹配成功的資訊來確定乙...
BM演算法總結
bm演算法,可以求乙個數列的最短遞推式。採用增量法,依次考慮每個數 若在這個位置上正確,則忽略 否則,類似拉格朗日插值法,找乙個滿足在前面位置都為0,這個位置上不為0的遞推式,進行修補。每當我們遇到乙個這樣的位置時,我們都可以得到乙個這樣的遞推式 用目前的遞推式,在0位置 即這個位置上 增加乙個 1...
BM演算法(筆記)
利用多位移動減少不必要的匹配。兩條字串 主串,匹配串 主串不動,匹配串去匹配 以下是匹配串針對主串而言 初始位置 最左對齊 匹配方向 從右向左 即初始位置對齊後,從匹配串最後乙個字元開始匹配 移動方向 從左向右 從右向左匹配時,出現不匹配的字元稱為 壞字元 壞字元有兩種情形,分別是 匹配串存在該壞字...