學(xué)習(xí)BM算法的姿勢

BM算法簡介

BM是字符串搜索算法聋呢。

字符串搜索單模式下有BF苗踪、RK、BM削锰、KMP算法通铲,其中BF是暴力搜索,RK是利用hash的一種算法器贩,BM和KMP是最常用的字符串匹配算法颅夺,假定模式串長度為m,文本長度是n磨澡,則BM最大算法復(fù)雜度在O(3n)碗啄,KMP算法復(fù)雜度在O(m+n)。

學(xué)習(xí)姿勢

BM算法恐怕我們一般都不會去寫稳摄,為何要去學(xué)習(xí)這種算法呢稚字?算法能訓(xùn)練人的邏輯能力,當(dāng)然要學(xué)厦酬。但是以什么樣的姿勢來學(xué)這種算法呢胆描,平心而論,這種算法學(xué)習(xí)復(fù)雜度算是比較高的仗阅,怎樣去學(xué)習(xí)比較合適呢昌讲?

就我個人的體會來說,按照算法思想和算法實現(xiàn)的套路來學(xué)習(xí)能顯著的降低學(xué)習(xí)復(fù)雜度减噪。怎么理解這個套路呢短绸?

  • 算法思想屬于高層一點的抽象,這里的算法思想結(jié)合上算法主流程來理解筹裕,互相印證醋闭,算法的主流程也算是算法思想這個層面
  • 算法實現(xiàn),算法主流程已經(jīng)放在算法思想中了朝卒,那么算法實現(xiàn)指什么呢证逻?看過《編程珠璣》,第二部分強調(diào)的就是算法寫好以后的優(yōu)化抗斤,沒錯囚企,這里指的就是優(yōu)化。對于這部分瑞眼,如果能理解就理解龙宏,理解不了就當(dāng)訓(xùn)練自己的算法思維了。

一旦以這種方式去理解這兩個算法伤疙,就會發(fā)現(xiàn)學(xué)習(xí)曲線降低了很多烦衣。

BM算法

BM = (壞字符規(guī)則 + 好后綴規(guī)則) (算法思想) + (壞字符hash數(shù)組實現(xiàn) + 好后綴巧算)(優(yōu)化)

BM的算法思想

BM算法與兩條規(guī)則有關(guān),理解了這兩條規(guī)則就理解了BM的算法思想。BM文本串和模式串是 從后向前 比較(特別注意一下這點)花吟。

壞字符規(guī)則

-
c是壞字符

第一個不匹配的就是壞字符,如圖就是文本串的c厨姚。不考慮好后綴的情況下衅澈,你會怎么辦,就是直接把模式串移動到壞字符的后面谬墙。

  • 移動到壞字符后面

如果說壞字符在模式串種存在今布, 直接移動到后面,可能移動過頭了拭抬。例如說如下情形部默,直接移動到壞字符c后面就過頭了。

  • 移動過頭了

    這時就需要結(jié)合好后綴來匹配造虎。

好后綴規(guī)則

好后綴有兩種情況

  • 情形一 好后綴在模式串種可以找到
    從后向前匹配傅蹂,在遇到壞字符之前,這些匹配的串就是好后綴算凿,如下橙色的ab就是好后綴份蝴。
  • 好后綴

好后綴可以在模式串種找到,直接就移動到模式串種的匹配處氓轰。

  • image.png
  • 情形二 好后綴在模式串種可以找不到

  • image.png

    這種情況下找不到婚夫,應(yīng)該怎么移動呢,就要找好后綴的后綴子串和模式串的前綴子串的最大匹配串

  • image.png

    如圖署鸡,找到ab的后綴子串和bb的前綴子串最長匹配串時b案糙,因此移動到b的位置。

算法思想講完了靴庆,就是這樣的时捌,再配合上主算法代碼就完成了算思想的學(xué)習(xí)

class Solution:
    def search(self, inputStr, pattern):
        if len(inputStr) < len(pattern):
            return -1
        bc = self.generateBC(pattern)
        suffix, prefix = self.generateGoodSuffix(pattern)

        i = 0
        patternLength = len(pattern)
        while i <= len(inputStr) - patternLength:
            j = patternLength - 1
            while j >= 0:
                if inputStr[i+j] != pattern[j]:
                    break
                j -= 1
            if j < 0: # match
                return i
            # exist bad chracter, i + bad c
            x = j - bc[ord(inputStr[i + j]) - ord('a')]
            #exist good suffix
            y = 0
            if j < patternLength - 1:
                y = moveByGoodSuffix(j, patternLength, suffix, prefix)
            i = i + max(x, y)
        return -1

    def moveByGoodSuffix(j, length, suffix, prefix):
        k = length - 1 - j # length of good suffix
        if suffix[k] != -1:
            return j - suffix[k] + 1
        r = j + 2
        while r < length - 1:
            if prefix[length - r + 1]:
                return r
        return j + 1

BM的算法實現(xiàn)(優(yōu)化)

對于壞字符位置以及好后綴的位置的計算屬于優(yōu)化部分,就不直接多說了撒穷,上代碼

  • 壞字符優(yōu)化
    def generateBC(self, m):
        bc = [-1] * 26
        for i in range(len(m)):
            bc[ord(m[i]) - ord('a')] = i        
        return bc
···
這里直接利用hash數(shù)組匣椰,以空間換時間。比較容易理解端礼,就不再贅述了禽笑。

- 好后綴計算
def generateGoodSuffix(self, m):
    length = len(m)
    suffix = [-1] * length
    prefix = [False] * length
    for i in range(length - 1):
        j = i
        k = 0
        while j>=0 and m[j] == m[length - 1 - k]:
            j -= 1
            k += 1
        if k: suffix[k] = j + 1
        if j == -1: prefix[k] = True
    return (suffix, prefix)

這個計算是個難點,但也不再贅述了蛤奥,可以到網(wǎng)上查一下佳镜。關(guān)鍵想說的就是,按照算法原理和實現(xiàn)的套路分開理解后凡桥,對于實現(xiàn)蟀伸,可以不再往下,學(xué)習(xí)到第一步算法原理就行了。算法實現(xiàn)就是優(yōu)化中的預(yù)先計算存儲的優(yōu)化思路啊掏。

小結(jié)

按照算法原理和算法實現(xiàn)(優(yōu)化)的套路蠢络,可以降低學(xué)習(xí)的復(fù)雜度,對于字符串搜索的KMP算法迟蜜,也可以用同樣的套路來進(jìn)行學(xué)習(xí)刹孔。KMP算法的算法實現(xiàn)(優(yōu)化)可以說是非常難以理解的,是一種動態(tài)規(guī)劃的算法娜睛,但是如果抓住這個套路髓霞,即使理解不了算法實現(xiàn)(優(yōu)化),我們理解了算法思想也是可以的畦戒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末方库,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子障斋,更是在濱河造成了極大的恐慌纵潦,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件配喳,死亡現(xiàn)場離奇詭異酪穿,居然都是意外死亡,警方通過查閱死者的電腦和手機晴裹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門被济,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人涧团,你說我怎么就攤上這事只磷。” “怎么了泌绣?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵钮追,是天一觀的道長。 經(jīng)常有香客問我阿迈,道長元媚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任苗沧,我火速辦了婚禮刊棕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘待逞。我一直安慰自己甥角,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布识樱。 她就那樣靜靜地躺著嗤无,像睡著了一般震束。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上当犯,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天垢村,我揣著相機與錄音,去河邊找鬼灶壶。 笑死肝断,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的驰凛。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼担扑,長吁一口氣:“原來是場噩夢啊……” “哼恰响!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起涌献,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤胚宦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后燕垃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枢劝,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年卜壕,在試婚紗的時候發(fā)現(xiàn)自己被綠了您旁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡轴捎,死狀恐怖鹤盒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情侦副,我是刑警寧澤侦锯,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站秦驯,受9級特大地震影響尺碰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜译隘,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一亲桥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧细燎,春花似錦两曼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽偿枕。三九已至,卻和暖如春户辫,著一層夾襖步出監(jiān)牢的瞬間渐夸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工渔欢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留墓塌,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓奥额,卻偏偏與公主長得像苫幢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子垫挨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350