模式匹配-KMP算法

KMP算法及求next函数值

今天复习到了串的模式匹配,有两种算法,一种简单的,还有一种改良后的,称为KMP算法。这篇说我对KMP算法的理解。

KMP

s串:主串;t串:子串

先说一下为什么要改良,简单的模式匹配效率低速度慢,而造成这种局面的根本就是一遍又一遍的返回,匹配失败后,s串回到下一个字符,t串回到第一个字符,这是不必要的,这就使效率变低。

如果在某趟匹配过程中,在Si和tj匹配失败后(即 t1t1…tj-1 = Si-j+1Si-k+2…Si-1 tj前所有字符与Si前所有字符匹配成功),i不返回到s串下一个字符,而是向右滑,存在tk前所有字符与Si前所有字符匹配成功,即 t1t2…tk-1 = Si-k+1Si-k+2…Si-1(原谅我不会打下标),k一定比j小,因为j后的字符还没有匹配到,所以tj的前k个字符与Sj的前k个字符匹配,即tj-k+1tj-k+2…tj-1 = Si-k+1Si-k+2…Si-1,以上可知,t1t2…tk-1=tj-k+1tj-k+2…tj-1
所以只要当匹配失败时,找出k值,就可以使tk对准Si继续匹配。

假设已有next函数情况下KMP代码:

int KMP(char s[],char t[],int next[])
{
   int i=pos,j=1;
   while(i<=s[0]%%j<=t[0])//没遇到结束符
   {
      if(j==0||s[i]==t[j])
        i++;j++;
      else j=next[j];//右滑
   }
   if(j>t[0]) return (i-t[0]);
   else return 0;
}

next

我们把要求的k值表示为next(j),next值取决于子串本身。next(1)=0是一定的。
设next(j)=k,即t1t2…tk-1=tj-k+1tj-k+2…tj-1
那么next(j+1)等于什么呢?
如果tk=tj,即t1t2…tk=tj-k+1tj-k+2…tj也就是 next(j+1)=k+1=next(j)+1
如果tk!=tj的话,可把现在tk!=tj当做模式匹配问题,现在tk与tj不匹配,那么应该找到k’可以继续匹配,即next(k)=k’,tk’=tj;则t1t2…tk’=tj-k’+1tj-k’+2…tj所以next(j+1)=k’+1=next(k)+1
如果tk’!=tj一直找下去k一直减小直至1,那么next(k)=0故next(j+1)=next(k)+1=1
代码如下:

void getnext(char t[],int next[])
{
   int j=1,k=0;
   next[1]=0;
   while(j<t[0])//未遇到结束符
   {
      if(k==0||t[j]==t[k])
        j++;k++;next[j]=k;
      else k=next[k];
   }
}

下面举一个例子

主串aabcbabcaabcaababc
子串abcaababc

next

j123456789
子串abcaababc
next(j)011122323

经以上代码测试正确,想自己测试一遍可进行测试,应该是没有问题的,如有问题请评论告诉我然后我修改哦

利用next函数进行匹配过程

第一趟:

aabcbabcaabcaababc
ab-caababc

b-位置失败,i=2,j=2,next(2)=1,故j=1,t1与S2比较

第二趟:

aabcbabcaabcaababc
abca-ababc

a-位置失败,i=5,j=4,next(4)=1,故j=1,t1与S5比较

第三趟:

aabcbabcaabcaababc
abcaababc

j++;i++;

第四趟:

aabcbabcaabcaababc
abcaaba-bc

a-位置失败,i=12,j=7,next(7)=3,故j=3,t3与S12匹配

aabcbabcaabcaababc
abcaababc

匹配成功

以上就是所有理解啦,我是参考课本和查找资料,自己理解并了解的,希望有什么不足请指出。bye

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BF算法和KMP算法都是串的模式匹配算法,但是它们的时间复杂度不同。BF算法的时间复杂度为O(m*n),其中m和n分别为主串和模式串的长度。而KMP算法的时间复杂度为O(m+n)。因此,当模式串较长时,KMP算法的效率更高。 下面是BF算法和KMP算法的介绍和演示: 1. BF算法(暴力匹配算法) BF算法是一种朴素的模式匹配算法,它的思想是从主串的第一个字符开始,依次和模式串的每个字符进行比较,如果匹配成功,则继续比较下一个字符,否则从主串的下一个字符开始重新匹配。BF算法的时间复杂度为O(m*n)。 下面是BF算法的Python代码演示: ```python def BF(main_str, pattern_str): m = len(main_str) n = len(pattern_str) for i in range(m-n+1): j = 0 while j < n and main_str[i+j] == pattern_str[j]: j += 1 if j == n: return i return -1 # 测试 main_str = 'ababcabcacbab' pattern_str = 'abcac' print(BF(main_str, pattern_str)) # 输出:6 ``` 2. KMP算法(Knuth-Morris-Pratt算法) KMP算法是一种改进的模式匹配算法,它的核心思想是利用已经匹配过的信息,尽量减少模式串与主串的匹配次数。具体来说,KMP算法通过预处理模式串,得到一个next数组,用于指导匹配过程中的跳转。KMP算法的时间复杂度为O(m+n)。 下面是KMP算法的Python代码演示: ```python def KMP(main_str, pattern_str): m = len(main_str) n = len(pattern_str) next = getNext(pattern_str) i = 0 j = 0 while i < m and j < n: if j == -1 or main_str[i] == pattern_str[j]: i += 1 j += 1 else: j = next[j] if j == n: return i - j else: return -1 def getNext(pattern_str): n = len(pattern_str) next = [-1] * n i = 0 j = -1 while i < n-1: if j == -1 or pattern_str[i] == pattern_str[j]: i += 1 j += 1 next[i] = j else: j = next[j] return next # 测试 main_str = 'ababcabcacbab' pattern_str = 'abcac' print(KMP(main_str, pattern_str)) # 输出:6 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值