KMP算法之next数组的求解思路

2.next数组的求解思路

本部分内容转自:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

  通过上文完全可以对kmp算法的原理有个清晰的了解,那么下一步就是编程实现了,其中最重要的就是如何根据待匹配的模版字符串求出对应每一位的最大相同前后缀的长度。我先给出我的代码:

复制代码
 1 void makeNext(const char P[],int next[])  2 {  3 int q,k;//q:模版字符串下标;k:最大前后缀长度  4 int m = strlen(P);//模版字符串长度  5 next[0] = 0;//模版字符串的第一个字符的最大前后缀长度为0  6 for (q = 1,k = 0; q < m; ++q)//for循环,从第二个字符开始,依次计算每一个字符对应的next值  7  {  8 while(k > 0 && P[q] != P[k])//递归的求出P[0]···P[q]的最大的相同的前后缀长度k  9 k = next[k-1]; //不理解没关系看下面的分析,这个while循环是整段代码的精髓所在,确实不好理解 10 if (P[q] == P[k])//如果相等,那么最大相同前后缀长度加1 11  { 12 k++; 13  } 14 next[q] = k; 15  } 16 } 
复制代码

   现在我着重讲解一下while循环所做的工作:

  1.   已知前一步计算时最大相同的前后缀长度为k(k>0),即P[0]···P[k-1];
  2.   此时比较第k项P[k]与P[q],如图1所示
  3.   如果P[K]等于P[q],那么很简单跳出while循环;
  4.   关键!关键有木有!关键如果不等呢???那么我们应该利用已经得到的next[0]···next[k-1]来求P[0]···P[k-1]这个子串中最大相同前后缀,可能有同学要问了——为什么要求P[0]···P[k-1]的最大相同前后缀呢???是啊!为什么呢? 原因在于P[k]已经和P[q]失配了,而且P[q-k] ··· P[q-1]又与P[0] ···P[k-1]相同,看来P[0]···P[k-1]这么长的子串是用不了了,那么我要找个同样也是P[0]打头、P[k-1]结尾的子串即P[0]···P[j-1](j==next[k-1]),看看它的下一项P[j]是否能和P[q]匹配。如图2所示

 

 

附代码:

复制代码
 1 #include<stdio.h>
 2 #include<string.h>
 3 void makeNext(const char P[],int next[])  4 {  5 int q,k;  6 int m = strlen(P);  7 next[0] = 0;  8 for (q = 1,k = 0; q < m; ++q)  9  { 10 while(k > 0 && P[q] != P[k]) 11 k = next[k-1]; 12 if (P[q] == P[k]) 13  { 14 k++; 15  } 16 next[q] = k; 17  } 18 } 19 20 int kmp(const char T[],const char P[],int next[]) 21 { 22 int n,m; 23 int i,q; 24 n = strlen(T); 25 m = strlen(P); 26  makeNext(P,next); 27 for (i = 0,q = 0; i < n; ++i) 28  { 29 while(q > 0 && P[q] != T[i]) 30 q = next[q-1]; 31 if (P[q] == T[i]) 32  { 33 q++; 34  } 35 if (q == m) 36  { 37 printf("Pattern occurs with shift:%d\n",(i-m+1)); 38  } 39  } 40 } 41 42 int main() 43 { 44 int i; 45 int next[20]={0}; 46 char T[] = "ababxbababcadfdsss"; 47 char P[] = "abcdabd"; 48 printf("%s\n",T); 49 printf("%s\n",P ); 50 // makeNext(P,next); 51  kmp(T,P,next); 52 for (i = 0; i < strlen(P); ++i) 53  { 54 printf("%d ",next[i]); 55  } 56 printf("\n"); 57 58 return 0; 59 }
复制代码

转载于:https://www.cnblogs.com/bill927/p/4844512.html

KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。next数组KMP算法中的一个重要概念,用于优化匹配过程。next数组求解过程如下: 1. 首先,我们需要定义一个next数组,next[i]表示当P串中第i个字符与S串中某个字符不匹配时,下一次匹配应该从P串的第next[i]个字符开始。 2. 对于P串中的每一个字符P[i],我们需要找到一个最长的相等前缀后缀长度k,使得P[0:k] == P[i-k:i]。这个k就是next[i]的值。 3. 求解next数组的过程可以使用递推的方式,从next开始,依次求解next、next、...、next[n-1]。具体地,我们可以使用两个指针i和j,其中i表示当前需要求解的next值的下标,j表示当前已经求解出的next值。初始时,i=0,j=-1。 4. 对于i>0的情况,我们需要不断地将j向前移动,直到找到一个满足P[j]==P[i-1]的位置。此时,我们就可以根据已经求解出的next[j]的值来求解next[i]的值。具体地,如果P[next[j]]==P[i-1],那么next[i]=next[j]+1;否则,我们需要继续向前递归,直到找到一个满足P[next[next[j]]]==P[i-1]的位置,此时next[i]=next[next[j]]+1。 5. 最后,我们得到了整个P串的next数组,可以使用KMP算法进行字符串匹配。 下面是一个Python实现的例子: ```python def get_next(p): n = len(p) next = [0] * n j = -1 for i in range(1, n): while j >= 0 and p[j+1] != p[i]: j = next[j] if p[j+1] == p[i]: j += 1 next[i] = j return next ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值