前一篇中介紹了字串kmp演算法,其利用失配時已匹配的字元資訊,以確定下一次匹配時模式串的起始位置。本文所要介紹的boyer-moore演算法是一種比kmp更快的字串匹配演算法,它到底是怎麼快的呢?且聽下面分解。
不同於kmp在匹配過程中從左至右與主串字元做比較,boyer-moore演算法是從模式串的尾字元開始從右至左做比較。下面討論的一些遞推式都與bm演算法的這個特性有關。
首先,我們一般化匹配失敗的情況,設主串\(y\)、模式串\(x\)的失配位置為i+j
與i
,且主串、模式串的長度各為\(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...
簡單模式匹配演算法 串的模式匹配
一 對乙個串中的某子串的定位操作稱為串的模式匹配 二 模式串 待定位的子串 三 基本思想 從主串中的第乙個位置起和模式串的第乙個字元開始比較 如果相等,則繼續比較後續字元 如果不等,則從主串的第二個字元起,重新用上一步的方法與模式串中的字元作比較 以此類推,直到比較完模式串的所有字元,則匹配成功,返...