KMP回溯

困惑了两天的kmp
主要还是j=nect[j],看了各个视频还有各个博客,我这笨脑子就是钻牛角尖转不过来圈。心里明知道那种可能是不存在的,想了各种方法证明,但是又感觉无从下手,今晚的茅塞顿开分享出来记录一下 话归正题 前面的最大公共前后缀应该没啥问题,这一部分的问题很容易解决,主要是 next数组的回溯问题。 比如一个模式串 假设两个变量i 和 j 前面的公式知道的话一直比较下去这个时候i应该在最后一位的b上面,j在比它少三位的a上面,就是在这个时候a和b不同 a b c a b c a b c b -1 0 0 0 1 2 3 4 5 6 这时候在和b比较之前的最大公共前后缀应该都是 a b c a b c 这个时候再加一的时候a和b不相等了,我一直觉得它应该一个一个减少逐个遍历,这个方法很蠢,而且也没必要,就是从现在相同的前后缀分别减少一位在一个个和它比较 。 下面看这个图,上面的例子最后面再补全 有图比较好理解了在这里插入图片描述还是这个视频讲解的比较清晰,b站上的懒猫老师。这个情况是A1和A2是相等的,但是再往前加一步的时候这时候两个就不相等了,这个时候按照回溯的想法应该是j回到c2的绿色方块,为什么呢,它匹配的时候如果此次匹配失败实际不用回到头,而是可以回到之前已经确定的最大前后缀上面,再进行比较。这个最大前后缀是在 j 里面存放着的,这个时候的前缀就应该是B1的那一块了,因为在 j 之前最大的前后缀就是B1和B2了,为什么直接就到B1了呢,A1A2相等的时候再+1不匹配的时候为什么不一个个减一再一个个匹配呢,它这个时候最大前后缀是看j的,相当于是找当前最大前后缀的最大前后缀。 当前最大前后缀A1,A1的最大前后缀是B1 所以要从B1开始比较,主要还是要理解j里面存放的最大前后缀就是B1 B2 这个就是当前模式串比较的最大前后缀。 这个时候B1是和B3相等的,为什么呢,因为先前的大A1A2是相等的,所以B2和B3也是相等的 B1和B2相等,所以B1和B3就相等了。 再加一张一模一样的省的划了 在这里插入图片描述为什么B3前面的一小块不用了呢?因为咱是要找j里面的最大公共前后缀。 所以就要B1后面的一个元素和B3后面的一个元素相比较,这时候B1B3是相等的,因为已经是当前最大前后缀了,还是要多琢磨,主要就是匹配失败的最大前后缀信息在j里面存放着,直接用j的前缀和后面的后缀比较 正如next数组的代码 j = next[j] 。在这里插入图片描述 j回到这个位置之后会继续和后面的B3比较,如果还不想等的话就回到当前j存放的最大前后缀里面,姑且认为前缀是第一个白框框和C1吧,c1前面的一个白框框加上c1是后缀,这时候继续比较两个最大公共前后缀前面的信息,再匹配失败的话就继续类推,按理说应该就到0了,nect 数组默认首元素是-1的话这时候j的值就被赋值-1。这个代码就是和人家一样的代码,不知不觉就记心里了,就不发了 再来最后一个琢磨挺久的一个例子,搞了我很久

a b c a b c a b c a b a

-1 0 0 0 1 2 3 4 5 6 7 8

看官辛苦,大概就是这个意思,其实就是想让你们可以的话就画个图,自己动手理解的话会更容易,和开头一样,这个时候i应该在末尾的b字符 j在末尾的前面三个字符a上面这个时候最大公共前后缀就是a b c a b c a b 开始想的是为什么不能遍历一个个挨个减少再分别比较呢,发现没必要, 当前缀从后往前减少 后缀从前往后减少的时候 容易迷糊,还是动手画个图吧。 这时候肯定是不想等的,如果相等的话前面的开头的abc必须要匹配到后面的开始的abc 这个时候再看j的位置,j在8号位置的c上面 就是这个时候j和末尾的字符不匹配。 再看j里面存放的最大公共前后缀, 是abcab 这个时候它就是上一个匹配成功的最大前缀, 是要看j里面保存的最大公共前后缀!因为这两个前后缀的信息在j里面 然后再用后面的字符c和末尾的a比较,发现不一样,这时候j在abcab前面的一个位置,这个位置的j存放的最大公共前后缀就是ab了,再用ab后面的一个值c和末尾的后缀ab后面的a相比,又不一样,然后就继续巴啦啦啊 主要还是为什么最大公共前后缀直接跳到了j里面,结合第一张图再琢磨琢磨看看前缀什么时候才能和后缀比较,就是当B1等于B3的时候,当B1等于B3也就相当于找B2嘛,找到了B2才能证明他俩相等。B1B2在哪, j 里面放着呗。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值