演算法筆記 字串搜尋2

2021-09-06 17:14:39 字數 2328 閱讀 7341

bm演算法的核心思想

在上述的描述中,我們可以把模式串與子串的對比看作是模式串在主串上的滑動。如果當前對比不匹配,模式串就向後滑動一位,與新的子串進行對比。

這樣的過程,每次模式串都是移動一位。但是再實際情況中,可能主串中的字元有 c,但是模式串中並不包含該字元。那麼,模式串其實可以直接移動到不含字元 c 的那一段,這樣模式串移動的距離增加了,提高了對比的效率。

請看如下圖示:

bm演算法原理分析

bm 演算法中包含兩個重要的規則:壞字元規則和好字尾規則。

壞字元規則

一般的字串匹配驗證,是從第乙個字元開始依次向後比較。而 bm 演算法確事從最後乙個字元向前乙個乙個比較。如下所示,我們會從模式串的最後乙個字元開始比較:

a,b,c,a,c,a,b,d,c

a,b,d

模式串中的最後乙個字元 d 與主串中的字元 c(壞字元) 不匹配,這個時候需要將模式串向後移動三位,徹底錯開主串中的 c 字元:

a,b,c,a,c,a,b,d,c

--------------a,b,d

繼續對比,發現模式串中的字元 d 和主串中對應的字元 a(懷字元) 不匹配,這個時候需要將模式串向後移動兩位,使得主串和模式串中的字元 a 相對應。

a,b,c,a,c,a,b,d,c

-----------------------a,b,d

通過上述過程得出以下規律:當發生不匹配的時候,我們把壞字元對應模式串中的下標位置記做 si。如果懷字元在模式串中存在,則在模式串中的下標位置記為 xi,如果不存在則 xi 值為 -1。那麼模式串向後移動的位數就是 si - xi。

上述過程模式串第一次移動的時候,si = 2,xi = -1。

上述過程模式串第二次移動的時候,si = 2,xi = 0。

注意:如果懷字元在模式串中多次出現,那麼 xi 的值取最靠近尾部的壞字元出現的位置。

僅僅根據壞字元規則是不能完全保證字元匹配的過程正確。例如主串為:aaaaaaaaaaaaaa,模式串為:baaaaa,那麼模式串不僅不會向後移動,反而會向前移動。第一次移動的時候,si = 0,xi = 5。

好字尾規則

a,b,c,a,c,a,b,d,c,b,a,a,c,b,d,a,b

-------------------b,d,b,d

觀察上述對比,子串與模式串不匹配,模式串需要向後移動,移動的位數可以利用壞字元計算。但是,我們也可以換一種方法控制模式串的移動。

在上述對比過程中,我們發現子串中 bd(好字尾) 與模式串中的 bd 匹配上了,那麼把 bd 記為。此時我們拿著,在模式串中繼續查詢。當找到另乙個時,直接將模式串中的另乙個滑動到該位置,與匹配,然後繼續比較模式串和子串的字元。如果在模式串中沒有找到,則直接將模式串滑動到最後。

a,b,c,a,c,a,b,d,a,b,d,a,c,b,d,a,b

-------------------d,a,b,d

看上述對比,好字尾bd 除了在模式串中的尾部匹配到以外,在其他位置並沒有匹配到。但是這個時候卻不能簡單的將模式串滑動到好字尾的後面,這樣的話就會錯過了後面正好匹配上的子串。

好字尾在模式串沒有找到另外一處匹配的時候,只要模式串和好字尾重疊,那麼模式串和子串就不可能完全匹配。但是,當模式串的頭部和好字尾的尾部有重疊,並且重疊部分的字元正好匹配,那此時的主串和模式串就有可能完全匹配的上。可參考上面的字元匹配示意過程!

針對這種情況,我們要充分考慮好字尾的子串是否與模式串的頭部字串有相互匹配的上得情況。這個時候,我們就要考慮衝好字尾的子串中找到乙個長度最長,並且能跟模式串的頭部匹配上的子串。然後,將模式串向後移動,移動到模式串的頭部和好字尾子串完全匹配上的地方。

針對好字尾的情況,我們同樣可以採用壞字元的方式確定模式串滑動的位置。那麼,如何恰當的運用這兩種規則呢?如果同時滿足這兩種規則的話,通過計算比較一下兩者需要模式串移動的距離,取其中移動距離最遠的方式。

總結**實現不總結了,難度太大,至今還沒研究透徹,留待日後補充吧。

初入演算法學習,必是步履蹣跚,一路磕磕絆絆跌跌撞撞。看不懂別慌,也別忙著總結,先讀五遍文章先,無他,唯手熟爾~

與諸君共勉

字串搜尋演算法

參考文獻 google boyer moore 1.前言 字串搜尋是乙個基本的操作,c庫函式中也提供了strstr 函式進行字串搜尋,應該是屬於線性搜尋。此外,為提高搜尋速度,人們又發展 出一些快速搜尋演算法,如boyer moore演算法等,其與線性搜尋的區別是當發現模式不匹配時,不是象線性搜尋那...

字串搜尋演算法總結

因為在網上搜尋hash演算法的知識,無意中又找到一些字串搜尋演算法。由於之前已經學習過一些搜尋演算法,覺得應該可以歸為一類。因此就寫一篇文章來記錄下學習的過程。問題 在一長字串中找出其是否包含某子字串。首先當然還是簡單演算法,通過遍歷來檢索所有的可能 public static int search...

字串搜尋

include include include includeusing namespace std char grid 100 100 word 100 int n m int x int y int xx yy void search if k len int main int t cin t ...