模式匹配 更快的Boyer Moore演算法

2021-09-07 04:50:03 字數 3418 閱讀 5402

前一篇中介紹了字串kmp演算法,其利用失配時已匹配的字元資訊,以確定下一次匹配時模式串的起始位置。本文所要介紹的boyer-moore演算法是一種比kmp更快的字串匹配演算法,它到底是怎麼快的呢?且聽下面分解。

不同於kmp在匹配過程中從左至右與主串字元做比較,boyer-moore演算法是從模式串的尾字元開始從右至左做比較。下面討論的一些遞推式都與bm演算法的這個特性有關。

首先,我們一般化匹配失敗的情況,設主串\(y\)、模式串\(x\)的失配位置為i+ji,且主串、模式串的長度各為\(n\)與\(m\),如下圖:

已匹配上的字元結構:

\[ y[i+j+1 \dots j+m-1] = x[i+1 \dots m-1] \]

已經匹配上的字元結構,

主串失配位置的字元

前一篇中的kmp演算法只利用第一條資訊,而boyer-moore演算法則是將這兩方面的資訊都利用到了,故模式串的移動更為高效。同時,根據這兩方面資訊(已匹配資訊與失配資訊),boyer-moore演算法引申出來兩條移動規則:好字尾移動(good-suffix shift)與壞字元移動(bad-character shift)。

moore教授在這裡給出bm演算法乙個例項,比如主串=here is a ****** example,模式串=example。第一次匹配如下圖:

在第一次匹配中,模式串在尾字元發生失配,而主串的失配字元為s,且s不屬於模式串的字元;因此下一次匹配時模式串指標應向右移動7位(壞字元移動)。第二次匹配如下圖:

第二次匹配也是在模式串尾字元發生失配,但不同的是主串的失配字元為p屬於模式串的字元;因此下一次匹配時模式串的p(從右開始第一次出現)應對齊於主串的失配字元p(壞字元移動)。第三次匹配如下圖:

在第三次匹配中,模式串的字尾mple完全匹配上主串,主串的失配字元為i,不屬於模式串的字元;那麼下一次匹配是模式串指標應怎麼移動呢(是壞字元移動,還是好字尾移動?)?bm演算法採取的辦法:移動步數=\(\max\\)。(具體移動步數的計算會在下面給出),這裡是按好字尾移動;第四次匹配如下圖:

第四次匹配的情況與第二次類似,應按壞字元移動,第五次匹配(模式串與主串完全匹配)如下圖:

因已匹配上的字元結構正好為模式串的字尾,故名之為好字尾。好字尾移動一般分為兩種情況:

移動後,模式串有子串能完全匹配上好字尾;

移動後,模式串只有能部分匹配上好字尾的子串

我們用陣列bmgs[i]表示模式串的失配位置為i時好字尾移動的步數。第一類情況如下圖:

第二類情況如下圖:

接下來的問題是應如何計算bmgs[i]呢?我們引入suff函式,其定義如下:

\[ suff[i]=\max \,1\le i < m \]

表示了模式串中末字元為x[i]的子串能匹配模式串字尾的最大長度。其中,suff[i]=m

綜合上述三類情況,bmgs陣列計算的實現**(參看[2]):

void prebmgs(char *x, int m, int bmgs)
壞字元移動是根據主串失配位置的字元y[i+j]而進行的移動。同樣地,我們用陣列bmbc[c]表示主串失配位置字元為c時壞字元移動的步數。壞字元移動一般分為兩種情況:

模式串x[0..i-1]有字元y[i+j]且第一次出現,如下圖:

整個模式串都不包含該字串,如下圖:

據此,可以將bmbc[c]定義如下:

\[ bmbc[c]=\min \ \]

表示距模式串末字元最近的c字元;若c字元未出現在模式串中,則bmbc[c]=m。c實現**:

void prebmbc(char *x, int m, int bmbc)
bmgs[i]的計算依賴於suff函式;如何更為高效的計算suff函式成為了接下來需要考慮的問題。符號標記的定義如下:

這裡所說的匹配指的是與模式串字尾的匹配。同樣地,一般化匹配過程,如下圖:

g < i < f則必有x[i]=x[m-1-(f-i)]=x[m-1-f+i]

c實現**:

void suffixes(char *x, int m, int *suff) }}

[1] moore, boyer-moore algorithm example.

[2] thierry lecroq, boyer-moore algorithm.

[3] sealyao, boyer-moore演算法學習.

使用模式匹配更快識別複雜C宣告

網上有乙個左右法則,其實左右法則適合程式分析,不適合人。我總結了對人來說乙個更簡單的法則 模式匹配.演算法如下 1.找到變數名。程式不容易做,人比較容易。2.除開變數名後,是它的型別宣告,可能有四種複雜,四種簡單模式 為了形式上完整 其中空格是變數的位置,可能是比較複雜東西。變數是指標 或?變數是值...

模式匹配 關於模式匹配的演算法實現2

參照我上篇部落格,只不過多了乙個識別率的演算法而已,還是參考歸併排序寫的,很簡單。上篇部落格位址 很多的解釋都在 裡面了,各位看看就明白了 author seen time 2015 09 20 include include include using namespace std struct p...

簡單模式匹配演算法 串的模式匹配

一 對乙個串中的某子串的定位操作稱為串的模式匹配 二 模式串 待定位的子串 三 基本思想 從主串中的第乙個位置起和模式串的第乙個字元開始比較 如果相等,則繼續比較後續字元 如果不等,則從主串的第二個字元起,重新用上一步的方法與模式串中的字元作比較 以此類推,直到比較完模式串的所有字元,則匹配成功,返...