Boyer-Moore演算法學習

來源:互聯網
上載者:User
1、概述

在用於尋找子字串的演算法當中,BM(Boyer-Moore)演算法是目前相當有效又容易理解的一種,一般情況下,比KMP演算法快3-5倍。

BM演算法在移動模式串的時候是從左至右,而進行比較的時候是從右至左的。

常規的匹配演算法移動模式串的時候是從左至右,而進行比較的時候也是是從左至右的,基本架構是:

j = 0;</p><p>while(j <= strlen(主串)- strlen(模式串)){<br /> for (i = 0;i < strlen(模式串) && 模式串[i] == 主串[i + j]; ++i)<br /> ;<br /> if (i == strlen(模式串))<br /> Match;<br /> else<br /> ++j;<br />}</p><p>

 

而BM演算法在移動模式串的時候是從左至右,而進行比較的時候是從右至左的,基本架構是:

j = 0;<br />while (j <= strlen(主串) - strlen(模式串)) {<br /> for (i = strlen(模式串) - 1; i >= 0 && 模式串[i] ==主串[i + j]; --i)<br /> if (i < 0)<br /> match;<br /> else<br /> ++j;<br />}<br />

顯然BM演算法並不是上面那個樣子,BM演算法的精華就在於++j

2、BM演算法思想

BM演算法實際上包含兩個並行的演算法,壞字元演算法和好尾碼演算法。這兩種演算法的目的就是讓模式串每次向右移動儘可能大的距離(j+=x,x儘可能的大)。

 

幾個定義:

例主串和模式串如下:

主串  :  mahtavaatalomaisema omalomailuun

模式串: maisemaomaloma

好尾碼:模式串中的aloma為“好尾碼”。

壞字元:主串中的“t”為壞字元。

好尾碼演算法

如果程式匹配了一個好尾碼, 並且在模式中還有另外一個相同的尾碼, 那

把下一個尾碼移動到當前尾碼位置。好尾碼演算法有兩種情況:

Case1:模式串中有子串和好尾碼安全匹配,則將最靠右的那個子串移動到好尾碼的位置。繼續進行匹配。

Case2:如果不存在和好尾碼完全符合的子串,則在好尾碼中找到具有如下特徵的最長子串,使得P[m-s…m]=P[0…s]。說不清楚的看圖。

壞字元演算法

當出現一個壞字元時, BM演算法向右移動模式串, 讓模式串中最靠右的對應字元與壞字元相對,然後繼續匹配。壞字元演算法也有兩種情況。

Case1:模式串中有對應的壞字元時,見圖。

Case2:模式串中不存在壞字元。見圖。

移動規則

BM演算法的移動規則是:

將概述中的++j,換成j+=MAX(shift(好尾碼),shift(壞字元)),即

BM演算法是每次向右移動模式串的距離是,按照好尾碼演算法和壞字元演算法計算得到的最大值。

shift(好尾碼)和shift(壞字元)通過模式串的預先處理數組的簡單計算得到。好尾碼演算法的預先處理數組是bmGs[],壞字元演算法的預先處理數組是BmBc[]。

3、程式碼分析定義

BM演算法子串比較失配時,按壞字元演算法計算模式串需要向右移動的距離,要藉助BmBc數組。

注意BmBc數組的下標是字元,而不是數字。

 

BmBc數組的定義,分兩種情況。

1、 字元在模式串中有出現。如,BmBc[‘k’]表示字元k在模式串中最後一次出現的位置,距離模式串串尾的長度。

2、 字元在模式串中沒有出現:,如模式串中沒有字元p,則BmBc[‘p’] = strlen(模式串)。

BM演算法子串比較失配時,按好尾碼演算法計算模式串需要向右移動的距離,要藉助BmGs數組。

BmGs數組的下標是數字,表示字元在模式串中位置。

BmGs數組的定義,分三種情況。

1、 對應好尾碼演算法case1:如:i是好尾碼之前的那個位置。

2、 對應好尾碼演算法case2:如所示:

3、 當都不匹配時,BmGs[i] = strlen(模式串)

在計算BmGc數組時,為提高效率,先計算輔助數組Suff。

Suff數組的定義:suff[i] = 以i為邊界, 與模式串尾碼匹配的最大長度,即P[i-s...i]=P[m-s…m]如:

舉例如下:

分析

用Suff[]計算BmGs的方法。

1) BmGs[0…m-1] = m;(第三種情況)

2) 計算第二種情況下的BmGs[]值:

for(i=0;i

if(-1==i || Suff[i] == i+1)

for(;j < m-1-i;++j)

if(suff[j] == m)

BmGs[j] = m-1-i;

3) 計算第三種情況下BmGs[]值,可以覆蓋前兩種情況下的BmGs[]值:

for(i=0;i

BmGs[m-1-suff[i]] = m-1-i;

如所示:

Suff[]數組的計算方法。

常規的方法:如下,很裸很暴力。

Suff[m-1]=m;

for(i=m-2;i>=0;--i){

q=i;

while(q>=0&&P[q]==P[m-1-i+q])

--q;

Suff[i]=i-q;

}

有聰明人想出一種方法,對常規方法進行改進。基本的掃描都是從右向左。改進的地方就是利用了已經計算得到的suff[]值,計算現在正在計算的suff[]值。

如所示:

i是當前正準備計算的suff[]值得那個位置。

f是上一個成功進行匹配的起始位置(不是每個位置都能進行成功匹配的,  實際上能夠進行成功匹配的位置並不多)。

q是上一次進行成功匹配的失配位置。

如果i在q和f之間,那麼一定有P[i]=P[m-1-f+i];並且如果suff[m-1-f+i]=i-q, suff[i]和suff[m-1-f+i]就沒有直接關係了。

代碼void preBmBc(char *x, int m, int bmBc[]) {</p><p> int i;</p><p> for (i = 0; i < ASIZE; ++i)</p><p> bmBc[i] = m;</p><p> for (i = 0; i < m - 1; ++i)</p><p> bmBc[x[i]] = m - i - 1;</p><p>}</p><p>void suffixes(char *x, int m, int *suff) {</p><p> int f, g, i;</p><p> f = 0;</p><p> suff[m - 1] = m;</p><p> g = m - 1;</p><p> for (i = m - 2; i >= 0; --i) {</p><p> if (i > g && suff[i + m - 1 - f] < i - g)</p><p> suff[i] = suff[i + m - 1 - f];</p><p> else {</p><p> if (i < g)</p><p> g = i;</p><p> f = i;</p><p> while (g >= 0 && x[g] == x[g + m - 1 - f])</p><p> --g;</p><p> suff[i] = f - g;</p><p> }</p><p> }</p><p>}</p><p>void preBmGs(char *x, int m, int bmGs[]) {</p><p> int i, j, suff[XSIZE];</p><p> suffixes(x, m, suff);</p><p> for (i = 0; i < m; ++i)</p><p> bmGs[i] = m;</p><p> j = 0;</p><p> for (i = m - 1; i >= 0; --i)</p><p> if (suff[i] == i + 1)</p><p> for (; j < m - 1 - i; ++j)</p><p> if (bmGs[j] == m)</p><p> bmGs[j] = m - 1 - i;</p><p> for (i = 0; i <= m - 2; ++i)</p><p> bmGs[m - 1 - suff[i]] = m - 1 - i;</p><p>}</p><p>void BM(char *x, int m, char *y, int n) {</p><p> int i, j, bmGs[XSIZE], bmBc[ASIZE];</p><p> /* Preprocessing */</p><p> preBmGs(x, m, bmGs);</p><p> preBmBc(x, m, bmBc);</p><p> /* Searching */</p><p> j = 0;</p><p> while (j <= n - m) {</p><p> for (i = m - 1; i >= 0 && x[i] == y[i + j]; --i);</p><p> if (i < 0) {</p><p> OUTPUT(j);</p><p> j += bmGs[0];</p><p> }</p><p> else</p><p> j += MAX(bmGs[i], bmBc[y[i + j]] - m + 1 + i);</p><p> }</p><p>}<br />

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.