KMP算法
自我感觉KMP算法一开始学起来有点绕,但是经过各种百度网上查阅材料,现在才对其有了一个更好的认识,为了加深
自己对其的理解,特地写下该文...
下面让我们探讨一下几个问题:
1.什么是KMP算法?
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫
里斯—普拉特操作(简称KMP算法)。
2.设计KMP算法的目的?
我们能够忍受朴素模式匹配的算法的低效吗?或许有的人无所谓,但是在很多情况下,通过挨个遍历的算法是非常
糟糕的,为了解决这个问题,上面提到的那三位前辈设计了该算法,KMP算法的核心是利用匹配失败后的信息,尽量
减少模式串与主串的匹配次数以达到快速匹配的目的。
3.KMP算法的具体实现?
KMP算法具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。
KMP算法的时间复杂度O(m+n)。
说了这么多估计还是一头雾水吧,凡事都要一步步来,接下来我来介绍一下KMP算法中所涉及到的一些名称的解释:
- 模式匹配:子串(模式串)的定位操作
- 前缀:指除最后一个字符外,字符串的所有头部子串
例如:'abax' 其中'a' 'ab' 'aba'为前缀
- 后缀:指除第一个字符外,字符串的所有尾部子串
例如:'xaba' 其中'a' 'ba' 'aba'为前缀
- 部分匹配值:字符串的前缀和后缀的最长相等前后缀长度
例如:'abca'
其中前缀为{a}{ab}{abc} 后缀为{a}{ca}{bca}
前后缀最长且相等为{a} 长度(部分匹配值)为1
估计又有小伙伴纳闷了,为什么要部分匹配值,这些到底有何用处?别急嘛,待我慢慢说来
- 举个例子 主串为 a b a b c a b c a c b a b,子串为 a b c a c
- 利用上面的例子我们很容易写出’ a b c a c’的部分匹配值为0 0 0 1 0,将部分匹配值写成数组形式就得到了next数组
next数组
下面用next数组来进行字符串匹配
第一趟
发现c与a不匹配,前面的a b是匹配的,查表可知最后一个匹配字符b所对应的部分匹配值为0,按照下面公式计算子串需要后移的位数
运动位数=已匹配字符数-对应的部分匹配值
因为2-0=2,所以将子串后移一位,进行下一趟
第二趟
主串 | a | b | a | b | c | a | 【b】 | c | a | c | b | a | b |
---|
子串 | | | a | b | c | a | 【c】 | | | | | | |
发现c与b不匹配,前面的a b c a是匹配的,查表可知最后一个匹配字符b所对应的部分匹配值为1,4-1=3,进行下一趟匹配
第三趟
子串全部匹配完成!!