字符串匹配问题——KMP算法

KMP算法
KMP是解字符串匹配这类题目的算法,又称“看毛片”算法。

如下图,给定一个长度为n的文本,给定一个长度为m 的字符串,求该字符串在给定文本的中出现的次数。KMP就是解决这一类题目的。

i 1
zzkzzzkzzzkzkkkz
zzkzzkzzkzzk
j 1

继续考虑上面的问题。首先我相信每个人都有一个笨蛋的想法,就是枚举在文本的起始位置i,然后把字符串从这个位置开始一个一个对比,如果遇到某一位j不相同就停止并i++,重新开始对比。这样的效率最坏的情况为O(m(n-1)),很不优秀。KMP其实就是基于这个笨蛋思想的优化。

i 6
a zzkzzzkzzzkzkkkz
b zzkzzkzzkzzk
j 5

我们可以假设当前对比文本位置i,字符串已经比较了j位,如果i和j+1不同其实我们不需要重新开始匹配,如果基于原来的基础之上,稍微将字符串往后移一移,这样j可以保留一定的位置,效率上得到提升。但是新位置还是要满足匹配,所以就要寻找一个最大的j’满足b[1..j’]和 a[i-j’+1..i]一致,然后继续用j’+1和i进行比较,如果不满足就继续进行以上过程。基本过程如下。

i 6
a zzkzzzkzzzkzkkkz
b zzkzzkzzkzzk
j 2 //2是能满足的最大j’,但是j’+1与i不匹配,所以继续

i 6
a zzkzzzkzzzkzkkkz
b zzkzzkzzkzzk
j 0

因为j之前已经匹配,所以寻找b[1..j’]和 a[i-j’+1..i]一致,其实就是寻找一段满足b[1..j’]和 b[j-j’+1..j]一致的自匹配,这个明显能够预处理出来,效率为O(n+m)。
主程序如下:

void KMP(){
    int j=0;
    for (int i=1;i<=n;i++){
        while (j>0&&b[j+1]!=a[i]) j=f[j];  //f[j]就是预处理的数组,存最大的j’
        if (b[j+1]==a[i]) j++;
        if (j==m) printf("%d\n",i-m+1),j=f[j];   //完成匹配,输出
    }
}

预处理f数组的过程与寻找匹配差不多,代码如下:

void work(){
    int j=0;
    for (int i=2;i<=m;i++){  //这里一定要从2开始,因为从1开始就全部匹配了,f[j]不能满足小于j
        while (j>0&&b[j+1]!=b[i]) j=f[j];
        if (b[j+1]==b[i]) j++;
        f[i]=j;
    }
}

KMP差不多就是这样,但是KMP存在有缺陷,一次只能拿一个字符串与文本比较,所以就有了AC自动机。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值