KMP串匹配算法原理及python实现

原理介绍

该算法用于匹配字符串。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串于主串的匹配次数以达到快速匹配的目的。

举个栗子

主串T = ‘abaacababcac’,模式串P=‘ababc’,用模式串P匹配主串T。

KMP算法的核心:计算模式串的前缀表(prefix table)。怎么 计算捏?

步骤1:写出模式串P的所有前缀

 步骤2:把每个前缀当成一个独立的串,然后分别找出每个串的最长公共前后缀,并将最长公共前后缀的长度记录下来。

注意:最长公共前后缀一定比原始串要短。

 以子串'abab'为例,它的最长公共前后缀为'ab',长度为2,就在该串前记录一个2.

 把其他串的最长公共前后缀也找到:

 不用管最后一行,给最前面加一个-1,就得到下面这列数字:

 这5个数形成的数组就是前缀表。

字符串匹配的过程:

从主串0号索引元素开始匹配:

 匹配失败时,将匹配失败元素的前缀表所对应下标的元素拉至当前位置,这就是KMP算法匹配过程的精髓之处。

 

 这里注意前缀表的下标是-1,其实就是把前缀表往右移动一格。

 匹配成功!

有时主串中可能会包含好几段模式串。所以还要往后继续匹配:

 这时候,已经遍历结束了,并且没有匹配成功,由此可知,只有一段模式串在主串中匹配成功了。

代码实现

def kmp(s, p):
    """
    s为主串, p为模式串, 如果s里有p,返回开始下标
    """
    next = get_next(p)
    i = 0
    j = 0  # 分别是s和p的指针
    while i < len(s) and j < len(p):
        if j == -1 or s[i] == p[j]:  # j==-1是由于j=next[j]产生
            i += 1
            j += 1
        else:
            j = next[j]

    if j == len(p):  # j走到了末尾,说明匹配到了
        return i - j
    else:
        return -1


def get_next(p):
    """
    p为模式串
    返回next数组,即部分匹配表
    """
    next = [0] * (len(p) + 1)
    next[0] = -1  # 在把PMT进行向右偏移时,第0位的值,我们将其设成了-1,是为了编程的方便
    i = 0
    j = -1
    while i < len(p):
        if j == -1 or p[i] == p[j]:
            i += 1
            j += 1
            next[i] = j  # 这是最大的不同:记录next[i]
        else:
            j = next[j]

    return next


if __name__ == '__main__':
    print(kmp("abaacababcac", "ababc")) # 5

总结

多debug几次,看看具体是怎么循环的,动手的同时多注重理解!

希望身边的小🐏人快快好起来!

我的后遗症是眼睛疼+疯狂打喷嚏?

附一张紧跟时代潮流的手机壳照片

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

弓早早o_O

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值