kmp再理解

来源:互联网 发布:时代光华管理课程知乎 编辑:程序博客网 时间:2024/05/29 08:19

kmp再理解
kmp中两个关键点:
1、next 函数的理解
2、在主串中如何的和next函数加以配合,进行模式匹配。
//=================================
1、next函数
作用:在next 函数中向前找最大位数相同(为了移动少一些,保证准确率),然后在和主串匹配时,向前加快移动位数。
理解:
j 1 2 3 4 5 6 7 8
模式串 b a b b a b a b

如上一个模式串,先模拟一个手工求解:(前提要清楚,假定模式串数组是从1开始,也可以假定是从0开始的)
例 j=5
j=5时对应的字符是’c’,向前看有四个字符a、a、a、b
第一步:从j=4向前取3个元素:a、a、b
从j=1向后取3个元素:a、a、a 不相等
第二步:从j=4向前取2个元素:a、b
从j=1向后取2个元素:a、a 不相等
第三步:从j=4向前取1个元素:b
从j=1向后取1个元素:a 不相等
第四步:从j=4向前取0个元素:
从j=1向后取0个元素: 相等
所以 next[j]=0+1; 这个加1不能忘记,在手动求解,并且j是从1开始的,若j 是从0开始的,则不用加1。
所以可以说:next函数就是找j前面的K+1(K=从头和从j-1有多少位是相同的),找到后,在和主串匹配时,若不匹配,就可以直接滑动到K+1的位置上来,和它相比较。
2、

如图,就是当不匹配时,滑动到next函数显示的位数进行比较
锦囊:其实next 函数可以理解为一个递归实现,想求next[j],可以看next[j-1]是否和j所对的元素相等,如果不相等,则在
next[(next[j-1])];一直推到K=0,然后next最后+1;若j从0开始,则不用加。
代码实现:

void  GetNext(STRING T,int next[]) {  ∥求模式串T的next函数值并存入数组next。     ∥字符数组下标从0开始,但数组next下标从1开始      j=1; next[1]=0; k=0;        while(j<T.length)      {   if(k==0||T.data[j-1]==T.data[k-1])           {   ++j; ++k; next[j]=k;  }          else  k=next[k];       }  }
int IndexKMP(STRING S, STRING T){ //利用模式串T的next函数求T在主串S中的位置的  //KMP算法。其中,T非空  i=0; j=1;  while(i<S.length&&j<=T.length)  {  if(j==0||S.data[i]==T.data[j-1])       { ++i; ++j; }  ∥继续比较后继字符     else j=next[j]; ∥模式串向右移动  }∥while  if(j>T.length)       return i-T.length+1; ∥匹配成功  else return 0;}

//==============================
答疑,为什么next[1]=0,而不是1?
因为要是1的话,当和第一个不匹配时,next[1]还是1,就不会向后移动了。

原创粉丝点击