2024/1/28学习

本文详细介绍了KMP算法,包括如何通过前缀表确定最大相等前后缀,以及在字符串匹配过程中如何利用next数组实现回退和匹配的动态调整,以提高查找效率。
摘要由CSDN通过智能技术生成

KMP算法

kmp算法是一种在一个串里寻找是否有另外一个串的强力算法,其核心是在匹配失败时寻找到上一次匹配成功的位置继续匹配,从而大大提高效率

KMP算法依靠于前缀表,前缀表记录了一串字符串以每一个位置为终点位置时的最大相等先后缀

那最大相等前后缀是什么?

首先得提及前缀和后缀

前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;

后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串;

例如一串字符AABAAF

这串字符的前缀为:

  1. A
  2. AA
  3. AAB
  4. AABA
  5. AABAA

后缀为:

  1. F
  2. AF
  3. AAF
  4. BAAF
  5. ABAAF

注:前后缀的看法都是从左往右看,所以相等前后缀都是从左往右比较,而不是对称!

那我们来寻找最大相等前后缀

将一串字符串挨个寻找

  1. A :严格意义来说它并没有前后缀,因为在这串字符串内它既是首字符,也是尾字符,所以它的最大相等前后缀为0;
  2. AA:它不含尾字符的前缀有A(第一个A)不含首字符的后缀有A(第二个A)两者相等,所以它的最大相等前后缀为1;
  3. AAB:因为后缀含有B,所以找不到相等的前缀,为0
  4. AABA,前缀有A,AA,AAB;后缀有A,BA,ABA;有一个相等前后缀,为1
  5. AABAA,前缀有A,AA,AAB,AABA;后缀有A,AA,BAA,ABAA;有两个相等的前后缀,为2;
  6. AABAAF,因为后缀有F,所以找不到相等前缀,为0;

于是就有以下前缀表:

A   A   B   A   A   F

0   1    0   1   2   0

这个前缀表的作用是什么?

首先得回到字符串匹配的问题上:

给你两串字符串,文本串和模板串

文本串:AABAABAAF

模板串:AABAAF

当我们一个一个字符匹配的时候,模板串前5个字符都能与文本串匹配,到第6个字符F并不能与B匹配,这时该怎么办呢?

则需要回到我们的前缀表,找到我们的最大前后缀为2,则此处的A从它开始数两个,即为AA

后缀处有一个这样的AA,前缀处也有一个这样的AA,我们在此处后缀的后方不匹配,则需要到达前缀处的后方进行重新匹配;

即从B开始重新匹配,将B即以后的字符串与原来F的位置(匹配失败的位置)开始匹配

即(将真前缀跳到真后缀处)

文本串:AABAABAAF

模板串:       AABAAF

这样即匹配成功

那代码该如何实现?

首先需要一个数组next[],用于记录当前字符串配对失败时,应该跳转的位置;

关于数组next[]

需要有

  1. 数据初始化
  2. 前后缀不同情况
  3. 前后缀相同情况
  4. 数据更新

初始化:首先定义i,jj指向前缀末尾位置,i指向后缀末尾位置,所以j从0开始,i从1开始;

前后缀不同时,即:s[j]!=s[i]时,将j回退,回退到的下标即为next[j]的值

相同时则模式串位置移动,继续匹配,更新next[]数组的值;

j=0;
next[0]=0;
for(i=1;i<=s.size();i++)
{
 while(j&&s[j+1]!=s[i])//如果不匹配
  {
     j=next[j];//回退
  }
  if(s[j+1]==s[i])//如果匹配
  {
  	j++;//移动
  }
  next[j]=j;//更新next数组
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值