Boyer-Moore算法

壞字符規(guī)則:

    后移位數(shù) = 壞字符的位置 - 搜索詞中的上一次出現(xiàn)位置
    例如:
        字符串: "HERE IS A SIMPLE EXAMPLE"
        搜索串: "EXAMPLE"
        以S為例,它對應(yīng)搜索串第6位, 上一次出現(xiàn)在搜索詞的''-1''(未出現(xiàn))
        即:
            后移 = 6 - (-1) = 7
            "HERE IS A SIMPLE EXAMPLE"
                   "EXAMPLE"
        再以P為例,對應(yīng)搜索串的第6位,在搜索詞的上一次第4位
        即:
            后移 = 6 - 4 = 2
            "HERE IS A SIMPLE EXAMPLE"
                     "EXAMPLE"

好后綴規(guī)則:

    (1) "好后綴"的位置以最后一個字符為準(zhǔn)。假定"ABCDEF"的"EF"是好后綴,則它的位置以"F"為準(zhǔn),即5(從0開始計算)。
    (2) 如果"好后綴"在搜索詞中只出現(xiàn)一次,則它的上一次出現(xiàn)位置為 -1。比如,"EF"在"ABCDEF"之中只出現(xiàn)一次,
        則它的上一次出現(xiàn)位置為-1(即未出現(xiàn))
    (3) 如果"好后綴"有多個,則除了最長的那個"好后綴",其他"好后綴"的上一次出現(xiàn)位置必須在頭部。
        比如,假定"BABCDAB"的"好后綴"是"DAB"、"AB"、"B",請問這時"好后綴"的上一次出現(xiàn)位置是什么?
        回答是,此時采用的好后綴是"B",它的上一次出現(xiàn)位置是頭部,即第0位。
        這個規(guī)則也可以這樣表達:如果最長的那個"好后綴"只出現(xiàn)一次,
        則可以把搜索詞改寫成如下形式進行位置計算"(DA)BABCDAB",即虛擬加入最前面的"DA"。
        
    后移位數(shù) = 好后綴的位置 - 搜索詞中的上一次出現(xiàn)位置
    
    例如:
        "HERE IS A SIMPLE EXAMPLE"
                 "EXAMPLE"
        所有的"好后綴"(MPLE、PLE、LE、E)之中,只有"E"在"EXAMPLE"中并且還出現(xiàn)在頭部,
        所以:
            后移 = 6(E在搜索詞中的位置) - 0(E在搜索詞中的上一次的位置) = 6。
            "HERE IS A SIMPLE EXAMPLE"
                           "EXAMPLE"

Boyer-Moore算法基本思想 : 每次后移這兩個規(guī)則之中的較大值。

def bm_match(target, part):
    target_len = len(target)
    part_len = len(part)
    # 臨時長度
    _ = len(part)
    cur = 1

    def bad():
        """ 生成壞詞規(guī)則 
            構(gòu)建搜索詞中各字符上一次出現(xiàn)位置
        """
        _dict = {}
        for index, value in enumerate(part):
            _dict[value] = index
        return _dict

    def good_postfix(cur):
        """ 生成好后綴規(guī)則 
            做好后綴和前綴的匹配
            # >>> b = 'EXAMPLE'
            # >>> for i in range(4,0,-1):
            # ...     print(b[-i:],b[:i], i)
            # ...
            # MPLE EXAM 4
            # PLE EXA 3
            # LE EX 2
            # E E 1
        """
        for i in range(cur, 0, -1):
            if part[-i:] == part[:i]:
                return i - 1
        return 0

    bad_dict = bad()
    while part_len <= target_len:
        # 判斷part與target對應(yīng)位是否相同
        if part[-cur] == target[_ - cur]:
            cur += 1
            if cur > part_len:
                return _ - part_len
        else:
            b = (part_len - cur) - bad_dict.get(target[_ - cur], -1)
            g = 0
            # 好后綴大于1個才進行好后綴匹配
            if cur > 1:
                g = part_len - good_postfix(cur)
            _ += max(b, g)
            cur = 1
    return -1


if __name__ == '__main__':
    print(bm_match('HERE IS A SIMPLE EXAMPLE', 'EXAMPLE'))
    # 輸出為17
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 參考文章 知乎:如何更好的理解和掌握 KMP 算法?從頭到尾徹底理解KMPKMP 算法(1):如何理解 KMP(原...
    Mjolnir1107閱讀 1,219評論 0 0
  • 9.3.3 快速排序 ??快速排序?qū)⒃瓟?shù)組劃分為兩個子數(shù)組,第一個子數(shù)組中元素小于等于某個邊界值,第二個子數(shù)組中的...
    RichardJieChen閱讀 1,949評論 0 3
  • 出生在哪里是被選擇的,長大后跟什么樣的人在一起,過什么樣的生活完全都是自己的主動選擇。這種選擇很多都取決你是怎樣的...
    白衣Eva陳慧琳閱讀 288評論 0 0
  • 聽說過 對我整夜失眠不值得!總愛把分手掛嘴邊!不值得你為他這樣 ,你不用想他的好,也不用換角度去想。你要想想日后的...
    yann2017閱讀 149評論 0 0
  • 這里描述了一套C語言編程風(fēng)格的標(biāo)準(zhǔn)。其中最重要的幾點是: 合理使用空白和注釋,使得我們通過代碼布局就可以清楚地看出...
    bigwhite閱讀 230評論 0 1

友情鏈接更多精彩內(nèi)容