KMP算法代码简单介绍

KMP算法代码简单介绍

KMP的核心就是获取目标字符串最大的前后缀交集长度列表,也就是大家经常看到的next列表。废话不多说,直接上代码!

def get_next(s: str) -> list:
    '''
    获取字符串最大的前后缀交集长度列表next
    e.g.: s = 'abcabe' -> next = [-1, 0, 0, 0, 1, 2]
    *******前后缀名词解释*******
    s的前缀为: 'a', 'ab', 'abc', 'abca', 'abcab'
    s的后缀为:'bcabe', 'cabe', 'abe', 'be', 'e'

    *******生成next列表的规则*******
    对s进行遍历的时候,next列表按照如下生成(计算next的值时不看最后一位):
    a - next[0] = -1
    ab - 无交集 0
    abc - 无交集 0
    abca - 无交集 0
    abcab - 交集 a 1
    abcabe - 交集ab 2
    '''
    # 初始化next列表
    l_next = [-1] * len(s)
    # 初始化循环指针,j为字符串遍历指针,k为生成next列表的循环指针
    j, k = 0, -1
    # 遍历字符串s
    while j < len(s) - 1:
        # 当k未指向字符串时,或者s[j]和s[k]相等时,j和k均往后移动一位
        # 然后,next列表next[j]保存k指针指向的位置
        if k == -1 or s[j] == s[k]:
            j += 1
            k += 1
            '''
            if s[j] == s[k]:
                l_next[j] = l_next[k]
            else:
                l_next[j] = k
            '''
            l_next[j] = k  # next列表next[j]保存k指针指向的位置
        else:
            # 这一句是非常关键的,也是最难理解的
            # 我也只是大概理解了,还未深入理解
            # 如果k已经指向字符串列表,并且s[j]不等于s[k]时
            # k指针回溯,意思是将k指向next列表next[k]的位置
            # 相当于是指向之前的一次s[j]==s[k]的位置
            k = l_next[k]
    return l_next

字符串生成next列表示意图:
字符串生成next列表示意图
有了核心的next列表,kmp算法就是利用next列表的信息,将2个字符串进行对比,如果目标字符串包含了指定的子串,就返回子串的索引位置。代码如下:

def KMP(s: str, p: str) -> int:
    '''
    s - 目标字符串;p - 待匹配子串
    返回子串在目标字符串中的索引位置
    '''
    i = j = 0
    l_next = get_next(p)
    print(p, '->', l_next)
    # 遍历两个字符串
    while i < len(s) and j < len(p):
        print('*' * 20)
        print(' '*i + 'v')
        print(s)
        print(' '*(i-j) + p)
        print(' '*i + '^')
        if j == -1 or s[i] == p[j]:
            i += 1
            j += 1
        else:
            j = l_next[j]

        # 字符串越界保护
        if i >= len(s) or j >= len(p): break
        # 如果子串p尾部超过了目标字符串,则不用再往后移动比较了
        if i-j + len(p) > len(s): return -1
    if j == len(p):
        return i - j
    return -1

if __name__ == '__main__':
    s, p = 'abcabcb', 'abcb'
    print('=' * 30)
    print('return:', KMP(s, p))

代码运行后的结果如下:
kmp算法比较过程和返回值
从上面的图片可以明显看到kmp算法移动比较的过程!如果大家感兴趣的话,可以自己把代码拷贝后去研究一下吧!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SoaringXu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值