zoukankan      html  css  js  c++  java
  • 03.串匹配算法

     
    def naive_matching(t, p):
        """
        朴素的串匹配算法
        从左到右逐个字符匹配,发现不匹配时,转去考虑目标串里的下一个位置是否与模式串匹配
        :param t: 目标串
        :param p: 模式串
        :return:
        """
        m, n = len(p), len(t)
        i, j = 0, 0
        while i < m and j < n:
            if p[i] == t[j]:
                i, j = i + 1, j + 1
            else:
                i, j = 0, j - i + 1
        if i == m:
            return j - i
        return -1
    
    
    def matching_kmp(t, p, pnext):
        """KMP串匹配
        如果i = -1,或者当前字符匹配成功(即t[j] == P[i]),都令i++,j++,继续匹配下一个字符;
        如果i != -1,且当前字符匹配失败(即t[j] != P[i]),则令 j 不变,i = next[i]
        next[j]即为j所对应的next值,此举意味着失配时,模式串P相对于目标串t向右移动了i - next [i] 位。
        :param t: 目标串
        :param p: 模式串
        :return:
        """
        i, j = 0, 0
        m, n = len(p), len(t)
        while i < m and j < n:  # i==m说明找到匹配
            if i == -1 or p[i] == t[j]:  # 遇到-1或字符相等,匹配下一对字符
                i, j = i + 1, j + 1
            else:  # 从pnext取的p的下一字符位置
                i = pnext[i]
        if i == m:  # 找到匹配,返回其开始下标
            return j - i
        return -1  # 无匹配,返回特殊值
    
    
    def gen_pnext(p):
        """
        生成针对p中各位置i的下一检查位置表
        计算最长相等前后缀的长度--递归求法
        已知next [0, ..., i],如何求出next [i + 1]呢?
        对于P的前i+1个序列字符:
        若p[i] == p[k],则next[i + 1 ] = next [i] + 1 = k + 1;
        若p[k ] ≠ p[i],如果此时p[ next[k] ] == p[i],则next[ i + 1 ] =  next[k] + 1,
        否则继续递归前缀索引k = next[k],而后重复此过程
        """
        i, k, m = 0, -1, len(p)
        pnext = [-1] * m  # 初始数组元素全为-1
        while i < m - 1:  # 生成下一个pnext元素值
            if k == -1 or p[i] == p[k]:
                i, k = i + 1, k + 1
                pnext[i] = k  # 设置pnext元素
            else:
                k = pnext[k]  # 退到更短相同前缀
        return pnext
    
    
    if __name__ == '__main__':
        print(naive_matching("ababc", "abc"))  # 2
        print(gen_pnext("abbcabcabbcaa"))  # [-1, 0, 0, 0, 0, 1, 2, 0, 1, 2, 3, 4, 5]
        print(gen_pnext("ababaaababaa"))  # [-1, 0, 0, 1, 2, 3, 1, 1, 2, 3, 4, 5]
        print(matching_kmp("ababc", "abc", gen_pnext("abc")))  # 2
    """参考博客:https://blog.csdn.net/dl962454/article/details/79910744"""

     优化后的next求法:

    def gen_pnext2(p):
        """
        生成针对p中各位置i的下一检查位置表
        优化:
         p[i] != t[j]时,下次匹配必然时p[next[i]]与t[j]匹配,如果p[i]=p[next[i]]
         必然p[next[i]]!=t[j],匹配失败,需要再次递归,即令next[i] = next[ next[i] ]。
        """
        i, k, m = 0, -1, len(p)
        pnext = [-1] * m  # 初始数组元素全为-1
        while i < m - 1:  # 生成下一个pnext元素值
            # p[k]表示前缀,p[i]表示后缀 
            if k == -1 or p[i] == p[k]:
                i, k = i + 1, k + 1
                if p[i] == p[k]:
                    # 因为不能出现p[i] = p[ next[i]],所以当出现时需要继续递归,k = next[k] = next[next[k]]
                    pnext[i] = pnext[k]
                else:
                    pnext[i] = k
            else:
                k = pnext[k]  # 退到更短相同前缀
        return pnext
  • 相关阅读:
    Adobe CS6 系列软件通用破解补丁 (amtlib.dll 含32位与64位)
    vs2010 快捷键大全
    js 处理json时间格式
    绑定DropDownListFor
    js插件
    NHibernate资料收集
    常用正则
    jQuery里面的datepicker日期控件默认是显示英文的,如何显示中文或其他语言呢?
    ASP.NET中使用Fusion Charts(Access+SQL)图表工具
    asp.net 2.0揭秘读书笔记二:使用Rich控件
  • 原文地址:https://www.cnblogs.com/fly-book/p/11704183.html
Copyright © 2011-2022 走看看