KMP小结

考虑a串和b串的暴力匹配
a串从位置i开始,匹配了b串前j个字符,这个时候j+1个字符失配了
不妨把a[i]直到a[i+j-1]取出记作c串
暴力匹配做的事情是从i到i+j-1这些位置开始匹配,但我们考虑到如果结束位置仍为i+j-1,这些暴力匹配出来地串的长度一定是小于j的。显然暴力匹配出来地极长的串,其为c串的后缀对后来的暴力匹配是有效的。如果不是c串的后缀,由于其长度小于j,于是匹配不完,并且在下一个字符失配。于是我们注意到,在上文模糊的“有效”定义下,暴力匹配下的终止位置总是不会移动的,而总是移动匹配下的起始位置。

于是我们失配后找到的第二个有效的暴力匹配串,假设从a[i’]开始,长度为j’。那么a[i’]…a[i’+j’-1]一定与a[i]…a[i+j’-1]相等,即第二个有效匹配串是c的前缀。同时他也是c的后缀,于是就有一点有用的性质。

考虑这个串在b串中的位置。由于c=b[1]…b[j],第二个有效匹配串是c的前缀,同时也是c的后缀,这意味着第二个有效匹配串同样也是b[1]…b[j]的前缀和后缀。事实上,如果我们在b串中匹配到了j这个位置,失配以后,第二个有效匹配串总是匹配到b[1]…b[j]串中极长的,使得前缀和后缀相等的字符串。这实际上给出了失配后,b串匹配到的位置的信息,也给出了第二个有效匹配串的长度。用next[j]表示b[1]…next[j] = b[j-next[j]+1]…b[j]的极长匹配的前缀后缀。

考虑next怎么求。如果b[next[j-1]+1]==b[j]那很好,next[j]=next[j-1]+1。那么显然next[j]最好的情况下只能是next[j-1]+1了。那如果失配,我们肯定是找b[1]…b[next[j-1]]的某个极长的前缀b[1]…b[s],使得
b[1]…b[s]=b[j-s]…b[j-1] (1)
再去判断b[s+1]=b[j]。
但是由于b[1]…b[next[j-1]=b[j-next[j-1]]…b[j-1] (由next指针的性质保证)
(1)式等价于 b[1]…b[s]=b[next[j-1]-s+1]…b[next[j-1]]
注意到这里有个重要前提就是next[j]一定<=next[j-1]+1,那么这个式子不就相当于求了b[1]…b[next[j-1]]的极长相同前后缀吗?那不就是next[next[j-1]]吗???
发出啊这的声音,显然这里如果有图的话会很易懂,但是笔者因为懂了所以不想画图,要是有路人在看的话,建议自己画一下图。
然后再看看b[next[next[j-1]]+1]=b[j]的情况,不行的话,就接着套next就行了。容易说明这总是满足极长相同前后缀的条件。

所以在a中匹配b,就是看a[i+1]==b[j+1],相等则++i,++j,否则j=next[j],再判断是否相等,一直到完全失配或者相等为止.
求next指针,就是t=next[j-1],b[t+1]==b[j],相等则next[j]=t+1.否则t=next[t],再看是否相等,直到完全失配或者相等.

暂时是看了一下别人kmp的思路,感觉讲的很杂乱,随便写了一点,还没具体实现过,感觉是可以的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值