不同版本的KMP算法总结

其实这是两年前我自己写的一篇总结,最近复习算法又给翻出来了,顺便发到博客上来。
从我个人的学经历来看,学习KMP算法最大的困难在于版本太多。如果你看完一个博客只是懵懂,想再看看另一个博客,那么就很有可能遇到另一个版本的KMP算法,会让你更加混乱,所以我觉得整理一下KMP算法的不同版本其实更加重要。
不同版本KMP算法的主要流程其实都是相似的,其不同之处在于预处理数组的定义。

第一种KMP算法的预处理数组叫做LPS数组(longest proper prefix which is also suffix),其中proper prefix是指不包含字符串本身的前缀(A proper prefix is prefix with whole string not allowed)。上述定义是从GeeksforGeeks中截取的,和它定义相同的参考书为《算法导论》。用中文解释的话,LPS[i]存储的是模式串前i+1个字符所组成的子串中,最大的相同前后缀。例如,字符串ababaca的LPS数组如下:

i0123456
前缀aababaababababaababacababaca
LPS[i]0012301

第二种KMP算法的预处理数组叫做next数组,也是网上博客提到最多的一种。不过next数组又要分两种:一种是K、M、P这三个人在其论文中所定义的next数组,它默认字符串是从1开始存储的,和它定义相同的参考书为严蔚敏的《数据结构》(C版)。这种数组相当于是把LPS数组整体右挪一位,然后在第一位填上“-1”后又整体加1得到的:

i0123456
前缀aababaababababaababacababaca
next[i]0112341

另一种next数组则默认字符串从0开始存储,许多网上的博客都用的是这种(毕竟我们一般不从1开始存储字符串)。这种数组是将LPS数组整体右挪一位,然后在第一位填上“-1”后得到的:

i0123456
前缀aababaababababaababacababaca
next[i]-1001230

针对这两种next数组,我有两点需要提醒:
1、LPS数组的最后一位,也就是LPS[m-1]实际上在KMP算法的主要流程中是派不上用场的(假设模式串长度为m),这也是为什么经过整体右移后得到的next数组依然可以用于KMP算法的原因。
2、如果有人问你一个字符串的next数组是什么,一般来说是要写第一种next数组。当然,你也可以先和人家声明你的字符串是怎么存储的,然后再写相对应的next数组。

第三种KMP算法的预处理数组叫做nextval数组,不过这种数组实际上不用于KMP算法,而是用于优化后的KMP算法。当字符串重复性很大的时候,使用nextval数组可进行预处理可以进一步降低时间复杂度。由于网上已有详细的手算next数组和nextval数组的讲解,我也就不再展开了,贴个链接好了:
https://www.cnblogs.com/alice123/articles/5701665.html
注:该博客中默认字符串从0开始存储。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值