KMP算法步骤解读

思路

  • 暴力算法

    • S[N] p[M]

      • S[]待匹配的长串

      • p[]模板串短串

    • 变量说明

      • t=0/1都可以,这里单独拉出来说明01都可

      • bool flag;

    • for(int i=t;S[i];i++) { flag=true; for(int j=t;p[j];j++) { if(s[i]!=p[j] )flag=false;break; } }

  •  

      • i j

      • i前为匹配完的区域(无符合要求)

      • i----j判断2串相同的区域

      • j为不相同的开始

      • 暴力做法为到j发现不满足,退回i再+1开始再次匹配串

  • KMP算法

  • 1.

     

  • 变量说明

    • S[N] p[M]

      • S[]主串

      • p[]子串

      • 字串从主串的第i位开始匹配到k+1位时不匹配停下

      • 当第k+1位不匹配时(图黄C) Next[k]存储着字串新的开头可以移动的位数

      • 即从(i+Next[k])重新匹配

  • 获取Next[]

    • 1.

       

    • 2.

    • 一个人能能走的多远不在于他在顺境时能走的多快,而在于他在逆境时多久能找到曾经的自己-KMP

    • 条件

      • 串为S[]

      • i已知

      • t已知

      • 数组从1开始

    • 图分析

    • next[i]匹配的最长串长推导1推导2推导3推导4推导5
      next[4]0
      next[5]10+10+1S[1]=S[5]S[0]=S[5]S[next[4]+1]=S[5]
      next[6]20+1+11+1S[2]=S[6]S[1+1]=S[6]S[next[5]+1]=S[6]
      next[7]30+1+1+12+1S[3]=S[7]S[2+1]=S[7]s[next[6]+1]=S[7]
      next[i-1]t--------
      next[i] (顺境)t+1--t+1S[t+1]=S[i]S[next[i-1]+1]=S[i]
      next[j-1]x----------
      next[j] (逆境)
    • 说明

      • next[i] 的求取为顺境情况

      • next[j]的求取为逆境情况

      • 前后缀相同为S[1,N]=S[M-(N-1),M] S[1,N] 表示从S[1]S[2]S[3]...S[N]

    • 1.顺境

      • next[i-1]=t

      • 顺境条件 S[t+1]=S[i] 即 S[next[i-1]+1]=S[i]

      • 顺境结果 next[i]=next[i-1]+1

    • 2.逆境

      • 逆境条件 不满足顺境条件即为逆境

      • 逆境结果 无法使用next[i]=next[i-1]+1 获取next[i]值

    • 逆境(S[j]!=S[x+1])处理

      • 条件1. next[j-1]=x

      • 条件2. 因为逆境的上一步是已经操作完毕的,我们由next[j-1]=x是匹配的最长串长可知 S[j-1-x+1]---到--->S[j-1]S[1]---到--->S[x] 完全相同

      • 逆境时多久能找到曾经的自己

      • 因为next[j]要存匹配的最长串长,即为S[1]--->S[] = S[]--->S[j]

      • 因为条件2可知我们判断的 S[j-x]...S[j-2] S[j-1] 与S[1]...S[x-1]S[x]对称

      •  

      • 此时因为逆序需要重新判断,但是S[j]前可能存在S[j-2]S[j-1]S[j]与S[1]S[2]S[3]的情况这时候我们需要倒回去找

      • 倒回去时当next[j-1]=0 时,next[j]必然为0或1, S[j]==S[1] 则next[j]=1 S[j]!=S[1]则next[j]=0

      • 倒回去时当next[j-1]!=0时,因为逆境导致我们的next[j]的获取不能按照常规顺境处理,且我们非暴力穷举的处理方法都依赖顺境,这时候我们需要找到曾今的自己

      • 这里next[j-1]=x

      • S[1] S[2]... S[x-1] S[x]

      • S[j-x] S[j-x+1]...S[j-2 ] S[j-1] 这时候可能看不出什么,那我再加一点点东西

      • S[1] S[2]... S[x-1] S[x] S[x+1]

      • S[j-x] S[j-x+1]...S[j-2 ] S[j-1] S[j]

      • S[j]遇到的逆境和S[x+1]遇到的逆境那么相同,曾今的自己是什么已经可以得知了

      • 过去的我不是现在的我,所以我们处理S[j]真正的方法是借用S[x+1]求next时用到的 next[x]

      • next[x+1] 求取过程:1.判断S[next[x]+1]==S[x+1]

      • next[j] 求取过程 1.判断S[next[x]+1]==S[j]

      • 如果上步看不懂可以视为,我将S[j]盖在S[x+1]上顶替S[x+1]来求一下next[j],求完next后便将S[j]送回原位

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只符华单推人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值