• exkmp


    扩展kmp

                                  广饶一中二校区李儒昊

    所谓扩展kmp指的是与kmp相似的求辅助数组的原理,但是本身与kmp关系不大。

    1.exkmp的用途:给定一个主串s和一个子串t,求出s中每一个后缀和子串t的最长公共前缀。

    2.算法推导:

    给定一个主串:S=aaaaaaaaaabaaa

                  T=aaaaaaaaaaa

    (下标都是从零开始!!!)

                     第一步

    需要有两个辅助数组:extand[i]和next[i];

    extand[i]:表示主串S以i开始的后缀与子串T的最长公共前缀。

    next[i]:表示子串T中以i开始的后缀与子串本身的最长公共前缀。

    首先看这个样例,很显然extend[1]=10。然后要求extend[2]。如果暴力求的话还要再用每个字符比较一遍太过麻烦。那么已经求得的extend[1]是不是可以利用呢?

    通过求得的extend[1]我们已经知道了:S[1...10]=T[1…10](不知道为什么的看定义去)。那么S[2..10]=T[2…10]。再算extend[2]时很明显extand[1]是没有用的,所以要从S[2]匹配。于是我们就要再引入一个数组next[i]。根据定义:

    因为next[2]=9;

    所以T[211]=T[110]

    所以T[210]=T[19](都删去一个字符)

    所以T[19]=S[210]

    所以extand[2]就等于9啊!!!多么神奇啊!

    第二步

    求完extand[2]后就可以知道这种求法原理是一种递推的。那么下面我们抛开特殊来看一般

    我们假设extand[1…k]已经求好(就像刚刚那个extand[1]已经求好一样)。并且,在以前匹配过程中在S当中所匹配到的最远位置是p那么这个最远的位置是不是就是i+extand[i]-1?(当前位置+匹配长度-1=匹配到的末端位置),其中i=1…k。不妨取这个最远的位置所对应的i是a很显然这个a是比p要小的。那么根据定义就可以推出            S[ap]=T[1p-a+1];

    所以 S[k+1p]=T[k+a+2p-a+1](都删去一段字符)

    我们再定义一个L,另L= extand[k-a+2](注意:这是定义的,不要老是纠结他究竟是为了什么,不然会很痛苦!!!这个会用到的。)

    那么根据L就可以推导出:T[1L]=T[k-a+2k+L-a+1]

    相信看到这里大多数人都已经懵逼了,那我们还是先回想一下next数组的定义,然后画个图就能懂了:

     

    是不是已经懂了?这是next数组的一个性质,前面在推extand[2]的时候应经用了。

                         第三步

    现在就出现了两种情况:

    (一) k+L<p

     

    图中红色的区域一定是相等的,即S[k+1k+1+L]=T[1L]

    因为前面已经推导过T[1L]=T[k-a+2k+L-a+1](1)

    并且S[k+1p]=T[k+a+2p-a+1](2)   p>k+L

    所以(1)式的右端点在(2)式右端点的左边。

    所以 多出来的那块=(p-a+1)-(k+L-a+1)

    再用p-[(p-a+1)-(k+L-a+1)]+1=k+L+1!

    所以就推出了S[k+1k+L+1]=T[1L]

    那么就可以知道蓝色的部分一定不会相等(因为L=extend[k-a+2]呀,如果相等的话那extend[k-a+2]不就等于L+1甚至更大了吗?)

    为什么k+L不能=p?  因为小于p时p之前一定存在一个字符与T[L+1]不匹配(图中蓝色区域)。如果等于p,那就无法判断下一位是否不匹配了。

    所以我们就得出了extend[k+1]=L,就求出来了!

    (二) k+L>=p

     

    明白了第一种,这种情况就比较通俗易懂啦!

    上图的紫色部分是未知的,红色部分是已经匹配的。因为在计算extend[1…k]时达到的最远位置是p,所以p之后的的位置无法访问。那怎么办?问我??这还用说:暴力求啊!

    从S[p+1]和T[p-k+1]开始匹配不就完啦?之后更新extend[a]+a和extend[k+1]+k+1的大小,后者的就更新最远位置p然后,,,就没有然后了!!!!

    那么next数组怎么求呢?其实next数组就是一个以T为主串,T为字串的一个特殊的扩展kmp!用上文介绍的相同算法计算next数组即可。

    唉!这就完了。写了整整一个晚上,因为下午刚学,连推公式带迷茫的痛苦了三个小时,终于完成了再附一个代码:

     

    Return 0!!!!!

  • 相关阅读:
    HAproxy 1.5 dev14 发布
    IBM/DW 使用 Java 测试网络连通性的几种方法
    Skype 4.1 Linux 发布,支持微软帐号登录
    Dorado 7.1.20 发布,Ajax的Web开发平台
    Aspose.Slides for Java 3.0 发布
    开发版本 Wine 1.5.18 发布
    BitNami Rubystack 开始支持 Ruby 2.0
    XWiki 4.3 正式版发布
    Silverlight实例教程 Out of Browser的Debug和Notifications窗口
    Silverlight实例教程 Out of Browser与Office的互操作
  • 原文地址:https://www.cnblogs.com/thmyl/p/6286173.html
Copyright © 2020-2023  润新知