KMP算法学习

字符串匹配问题

查找某个长度为m的字符串P在文本字符串中出现的位置,文本串T的长度为n。
- 求P在T中第一次出现的位置
- 求P在T中所有出现的位置


一般解法

首先使用比较直观的平凡算法来求解该问题。基本思路是扫描T,先找到P第一个字符的出现位置,再继续匹配其后续的若干个字符,若出现不同则匹配失败返回,继续向后查找P的第一个字符。
时间复杂度为O(mn)阶。


KMP算法

KMP(Knuth-Morris-Pratt)算法主要是在匹配失败时做了改进。它利用模式串P中可能出现重复的特征,使每次P与T匹配失败后,不会再从头开始扫描P。

为P定义next数组

P中下标为i的字符的next[i]定义为:字符i之前的子串中相同前后缀的最大长度。

例子
定义 T: abababdaa P: abababcd
当扫描到下标为5的字符‘c’时匹配失败:

T:  ababab|d|aa
           |
P:  ababab|c|d

字符c之前的子串为ababab,有最长的相同前缀和后缀为abab,故next[5]为4。

KMP

接上文,匹配失败后将P右移next[5]位,继续下一次匹配。

例子

T:  ababab|d|aa
           |
P:      ab|a|babcd

可以看到,next[i]是在该字符处匹配失败时P应该右移的字符数,也就是扫描指针应该左移的字符个数。


性能讨论

字符集大小的影响
T和P可选择的字符集越大,则越不容易匹配成功,每次匹配失败的位置会更加靠前,性能较接近于平凡算法。

模式串P的特征
如果P的长度m较小,则性能改进不会很明显;
若P中重复很少,性能也不会太好,因为每次搜索时P实际右移的距离不大,与平凡解法接近。

较好情况
若字符集小且m较大时,KMP算法跳跃扫描的优势就能得到体现,可以得到较明显的性能改进。


参考
《计算机算法引论》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值