zoukankan      html  css  js  c++  java
  • 【数据结构】KMP 算法

    受阮一峰博客关于KMP字符串匹配算法启发,实现python的kmp实现, 比较清楚明白
    地址为 http://www.ruanyifeng.com/blog/2013/05/Knuth–Morris–Pratt_algorithm.html

    def next_arr(s: str) -> list:
        """
        计算 《部分匹配表》
        https://www.cnblogs.com/dahu-daqing/p/9302668.html
        http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html
        :param s:
        :return:
        """
    
        def calc(p: str) -> int:
            if len(p) > 1:
    
                # "前缀"指除了最后一个字符以外,一个字符串的全部头部组合
                prefix_com = [p[:i + 1] for i in range(len(p) - 1)]
                # "后缀"指除了第一个字符以外,一个字符串的全部尾部组合
                suffix_com = [p[i + 1:] for i in range(len(p) - 1)]
    
                common_has_len = 0  # 共有元素的长度
    
                for p_str in prefix_com:
                    for j_str in suffix_com:
                        if p_str == j_str:
                            common_has_len = len(j_str)
                return common_has_len
            else:
                return 0
    
        tmp = []
        for i in range(len(s)):
            t = s[:i + 1]
            tmp.append(calc(t))
        return tmp
    
    
    def bf(s: str, p: str) -> int:
        ret = -1
        """
    
        :param s: 目标串
        :param p: 模式串
        :return:
        """
        if len(s) < len(p): return ret
    
        k = 0
        k_end = len(p)
    
        while k <= len(s) - len(p):
            ts = s[k:k_end]
            if ts == p:
                ret = k
                break
            else:
                k += 1
                k_end += 1
    
        return ret
    
    
    def bf_example():
        s = "BBC ABCDAB ABCDABCDABDE"
        p = "ABCDABD"
        print(bf(s, p))  # 输出匹配成功15的下标
    
    
    def kmp(s: str, p: str) -> int:
        next = next_arr(p)
    
        ret = -1
    
        sl = list(s)
        pl = list(p)
    
        if len(sl) < len(pl): return ret
    
        start = 0
    
        while start <= len(sl) - len(pl):
    
            eq_num = 0  # 已匹配的字符数
            for i in range(len(pl)):
                if pl[i] != sl[start + i]:
                    break
                else:
                    eq_num += 1
    
            if eq_num == 0:
                start += 1
            elif eq_num == len(pl):
                # 全部匹配成功
                ret = start
                break
            else:
                # 模式串不匹配字符的前一个字符
                next_num = next[eq_num - 1]
                # 移动位数 = 已匹配的字符数 - 对应的部分匹配值
                start += (eq_num - next_num)
    
        return ret
    
    
    if __name__ == '__main__':
        s = "BBC ABCDAB ABCDABCDABDE"
        p = "ABCDABD"
        print(kmp(s, p))
    
    
    “年轻时,我没受过多少系统教育,但什么书都读。读得最多的是诗,包括烂诗,我坚信烂诗早晚会让我邂逅好诗。” by. 马尔克斯
  • 相关阅读:
    js中的this
    js中的call和apply
    自定义ListView无法响应点击事件
    Listview滑动超出显示区域时getChildAt(arg2)异常错误
    cocos2d-x在eclipse上搭建开发环境
    阿里云服务器CentOS 5.7(64位)安装配置LAMP服务器(Apache+PHP5+MySQL)
    如何在eclipse模拟器上运行下载好的apk程序
    百度RSS整理
    vtigercrm学习(二)
    Android桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果
  • 原文地址:https://www.cnblogs.com/jzsg/p/11213674.html
Copyright © 2011-2022 走看看