美文网首页
Boyer-Moore算法

Boyer-Moore算法

作者: Cichar | 来源:发表于2017-06-05 21:57 被阅读0次

    坏字符规则:

        后移位数 = 坏字符的位置 - 搜索词中的上一次出现位置
        例如:
            字符串: "HERE IS A SIMPLE EXAMPLE"
            搜索串: "EXAMPLE"
            以S为例,它对应搜索串第6位, 上一次出现在搜索词的''-1''(未出现)
            即:
                后移 = 6 - (-1) = 7
                "HERE IS A SIMPLE EXAMPLE"
                       "EXAMPLE"
            再以P为例,对应搜索串的第6位,在搜索词的上一次第4位
            即:
                后移 = 6 - 4 = 2
                "HERE IS A SIMPLE EXAMPLE"
                         "EXAMPLE"
    

    好后缀规则:

        (1) "好后缀"的位置以最后一个字符为准。假定"ABCDEF"的"EF"是好后缀,则它的位置以"F"为准,即5(从0开始计算)。
        (2) 如果"好后缀"在搜索词中只出现一次,则它的上一次出现位置为 -1。比如,"EF"在"ABCDEF"之中只出现一次,
            则它的上一次出现位置为-1(即未出现)
        (3) 如果"好后缀"有多个,则除了最长的那个"好后缀",其他"好后缀"的上一次出现位置必须在头部。
            比如,假定"BABCDAB"的"好后缀"是"DAB"、"AB"、"B",请问这时"好后缀"的上一次出现位置是什么?
            回答是,此时采用的好后缀是"B",它的上一次出现位置是头部,即第0位。
            这个规则也可以这样表达:如果最长的那个"好后缀"只出现一次,
            则可以把搜索词改写成如下形式进行位置计算"(DA)BABCDAB",即虚拟加入最前面的"DA"。
            
        后移位数 = 好后缀的位置 - 搜索词中的上一次出现位置
        
        例如:
            "HERE IS A SIMPLE EXAMPLE"
                     "EXAMPLE"
            所有的"好后缀"(MPLE、PLE、LE、E)之中,只有"E"在"EXAMPLE"中并且还出现在头部,
            所以:
                后移 = 6(E在搜索词中的位置) - 0(E在搜索词中的上一次的位置) = 6。
                "HERE IS A SIMPLE EXAMPLE"
                               "EXAMPLE"
    

    Boyer-Moore算法基本思想 : 每次后移这两个规则之中的较大值。

    def bm_match(target, part):
        target_len = len(target)
        part_len = len(part)
        # 临时长度
        _ = len(part)
        cur = 1
    
        def bad():
            """ 生成坏词规则 
                构建搜索词中各字符上一次出现位置
            """
            _dict = {}
            for index, value in enumerate(part):
                _dict[value] = index
            return _dict
    
        def good_postfix(cur):
            """ 生成好后缀规则 
                做好后缀和前缀的匹配
                # >>> 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对应位是否相同
            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
    

    相关文章

      网友评论

          本文标题:Boyer-Moore算法

          本文链接:https://www.haomeiwen.com/subject/wguwfxtx.html