kmp算法学习

  最近看了一些神犇的博客,对kmp有了初步的一点认识,简单地写一下。

  kmp是用来在一个字符串A中查找一个子串B的,用传统的方法是从A的第一位开始和B的第一位比较,若相等则比对下一位,B的某一位与对应的A的字符不匹配,则回过头,将A的第二位同B的第一位比较,重复之前的操作,时间效率为O(m*n),我们可以知道此方法效率不高,主要原因是做了许多多余的操作,因为一些位置不需要继续判断,可以直接跳过的,kmp算法就是去掉了多余的操作,本身求解时间效率O(n),预处理时间效率O(m),故总时间效率为O(m+n).

  kmp算法与朴素算法不同的是,当发现不匹配时,朴素算法A的指针将回溯到本次匹配第一个字符的位置,然后加一,而kmp算法则会避免这种回溯。

  我们通过下面这个例子来了解一下。

  A  ababbababa

  B  ababa

  在A中查B,从第一位开始比对,直到发现最后一位不匹配,如果是朴素算法,就会将A的指针回溯到第二个字符的位置,B的指针回到1位置继续比较,然而我们会发现此时A[2]=B[2],而B[1]<>B[2],则必定A[2]<>B[1],则个操作就没必要了。而使用kmp时,我们可以将B的指针放在2的位置(绿色部分),此时A[3..4]=B[1..2],指针加一继续比较下一位即可。

  我们如何知道kmp算法中怎么指针移动呢,我们用f数组来保存对于B的每一位字符在匹配不成功时所要退回到的位置,换一种说法就是f[i]表示B[1..i]这个字符串中最大前缀与后缀相同的长度,可通过递推快速得出f数组所保存的值。

kmp匹配代码

procedure kmp(a,b:ansistring);
var p,q,lena,lenb:longint;
begin
  p:=1; q:=0; ans:=0; lena:=length(a); lenb:=length(b);
  while p<=lena do
   begin
     while (q>0)and(b[q+1]<>a[p]) do q:=f[q];
     if b[q+1]=a[p] then q:=q+1;
     if q=lenb then
      begin
        ans:=ans+1; q:=f[q];//后面这个赋值是用于统计A中总共出现B几次的,如果只判断是否出现过则可以删去
      end; p:=p+1;
   end;
end;

求f数组的预处理代码

procedure work(a,b:ansistring);
var p,q,lena,lenb:longint;
begin
  f[1]:=0; p:=2; q:=0; lena:=length(a); lenb:=length(b);
  while p<=lenb do
   begin
     while (q>0)and(b[q+1]<>b[p]) do q:=f[q];
     if b[q+1]=b[p] then q:=q+1;
     f[p]:=q; p:=p+1;
   end;
end;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值