KMP模式匹配算法

本文深入讲解了Knuth-Morris-Pratt(KMP)字符串查找算法的原理与实现过程,包括如何构建next数组来提高匹配效率,并附带了详细的示例说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法。整个KMP的重点就在于当某一个字符与主串不匹配时,我们应该知道j指针要移动到哪里。


如图:C和D不匹配了,我们要把j移动到哪?显然是第1位,因为如下面蓝框所示,前面A已经匹配。


下面也如此:


可以把j指针移动到第2位,因为前面有两个字母是一样的


至此我们得知,当匹配失败时,j要移动的下一个位置k。存在着这样的性质:最前面的k个字符和j之前的最后k个字符是一样的。

用数学公式表示如下:
P[0 ~ k-1] == P[j-k ~ j-1]

可以通过递推求得next 数组,代码如下所示:

 void Next(char* p,int next[])  
 {  
     int pLen=strlen(p);  
     next[0]=-1;  
     int k=-1;  
     int j=0;  
     while (j<pLen-1)  
     {  
         //p[k]表示前缀,p[j]表示后缀  
         if (k==-1 || p[j]== p[k])  
         {  
             ++k;  
             ++j;  
             next[j]=k;  
         }  
         else  
         {  
             k=next[k];  
         }  
     }  
 }

next[j]的值(也就是k)表示,当P[j] != T[i]时,j指针的下一步移动位置。

当j为0时,如果这时候不匹配,j已经在最左边了,不可能再移动了,这时候要应该是i指针后移。所以在代码中才会有next[0] = -1;这个初始化。


P[k] != P[j]


从代码上看应该是这一句:k = next[k];为什么是这样子?你看下面应该就明白了。


有了next数组之后就一切好办了,我们可以写KMP算法了:

int KmpMatch(char* s,char* p)  
 {      
      int i=0;  
      int j=0;  
      int sLen=strlen(s);  
      int pLen=strlen(p);  
      while (i<sLen&&j<pLen)  
      {  
          //①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++      
          if (j==-1 || s[i]== p[j])  
          {  
              i++;  
              j++;  
          }  
          else  
          {  
              //②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]        
              j=next[j];  
          }  
      }  
      if (j==pLen)  
          return i-j;  
      else  
          return -1;  
  }

备注:KMP算法是经典算法,原理和一些框图参考了网上的技术博客,这里融入自己的一些理解记录,以加深自己对算法的理解,同时与广大网友交流,欢迎批评指正!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值