说说KMP算法

以前一直没搞懂kmp算法,可能没用心去理解,最近茅厕顿开,搞明白了。

 

kmp短小精妙,能将串比较减少到O(m+n)的复杂度,比一般的O(m*n)要强得多。

 

要想理解kmp,得先了解next数组的奥妙。

 

先引用网上一段解释:

 

next数组存储的是一个失败函数,也就是自动机遇到没匹配上的字符时要跳回的状态,


例如 ababaa,其中字符代表要匹配的输入,数字代表状态


于是有失败函数,此函数满足一个映射,就是next数组,这个串的失败函数是


s a b a b a a
f  0 0 1 2 3 1

 

失败函数中数字代表的状态是上面串的最长真后缀,例如

s=3时串为aba,f=1串为a,于是a是aba的最长真后缀。

失败函数的作用,当s=3时输入的字符没匹配上,那么自动机就会从3状态跳回1状态,

因为1对应的串是3的最长真后缀,直到3之前都被匹配上了,那么3的最长真后缀也就被匹配上了,

即直到1被匹配上了,所以这样就避免了重复的匹配。

举例,判断上面的字符串是否是abababaab的字串,

首先ababa都被匹配,到下一个a时没匹配上于是跳到f(5)=3,跳到3,即aba是ababa的最长真后缀,

所以aba肯定会被匹配(因为ababa能被匹配),然后baab也被匹配,就是这个过程。

 

根据上边的话,我理解next数组,保存的就是当前位置最长真后缀,相信你也是茅厕顿开了吧.

 

下边看算法:

 

next数组求法:

 

 

 

kmp查找算法(跟next求法神似):

 

 

 

希望对读者有所帮助^_^

 

 

 

下边介绍一个扩展的用法:

 

“GOOD”串

时间限制(普通/Java):1000MS/3000MS          运行内存限制:65536KByte
总提交:266            测试通过:33

描述

Cc最近对字符串很感兴趣,由其对一个字符串的子串的子串作了研究。如果一个字符串A的子串和另一个给定的字符串B相等,他会很高兴,并且把A称作B的Good String。
现在有两个很长的字符串,Cc想知道第一个字符串的某些子串是否是第二个字符串的Good String,于是Cc会询问你第一个字符串的从第a位到第b位的子串是否是第二个字符串的Good String,若是则回答“Yes”,否则回答“No”。

输入

多组数据,每组数据第一行2个数L1,L2(1<=L1,L2<=100000)表示两个字符串的长度,接下来两行是分别是长度为L1和L2的字符串(由小写字母构成),接下来一行一个数Q,表示询问的个数。接下来Q行每行两个数a,b(1<=a<=b<=L1)表示询问第一个字符串的从第a位到第b位的子串是否是第二个字符串的Good String。输入数据以0 0结束。

输出

每组数据输出一个数T占一行,表示Q个询问中回答“Yes”的个数。

样例输入

7 3
abcdefg
def
3
1 7
2 6
3 5
0 0

样例输出

2

 

 

考查的就是kmp+二分查找

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值