小记KMP算法
近日温习数据结构,至KMP算法,虽知特征函数next[j]生成步骤,奈何不明其算法,惑不已。一阵写写画画修修补补之后,方才补得如下代码,以备后查。
PS:KMP算法根据模式字符串P本身的性质,省略了P和目标字符串T进行比较时一些不可能匹配的步骤,提高了匹配的时间性能。
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
//KMP算法得到next(j) 官方版
void getNext(char * p,int lengthP,int * next)
{
int j=0,k=-1;
next[0] = -1;
while(j<lengthP)
{
if(k==-1||p[j]==p[k])
{
j++;
k++;
next[j]=k;
}
else k=next[k];
}
}
//已知next(0)~next(j0),求next(j0+1),包含递归调用
//p:模式字符串P
//j0:表示已知next(0)~next(j0),求next(j0+1)
//j:该参数的传入值根据递归层次的不同而变化
//next:模式字符串的特征函数
//已知next(j0)=k+1,即P[j0-1-k] ... ... P[j0-1] = P[0] ... ... P[k]
//若P[j0]=P[k+1],则next(j0+1)=k+2;若p[j0]!=P[k+1],则必须求l使得P[k-l-1] ... ... P[k]=P[0] ... ... P[l]。
//若P[j0]=P[l+1]则next(j0+1)=l+2;若P[j0]!=P[l+1],则必须求m使得P[k-m-1] ... ...P[h]=P[0] ... ... P[m]
//以此类推下去,最后有两种情况,一是存在某个数n,满足了P[j0]=P[n+1],此时next(j0+1)=n+2;
//另一种情况是不存在这样一个数,迭代到最后只能让P[0]对应P[j0+1],即next(j0+1)=0
int produceNext(char *p,int j0,int j,int *next)
{
if(0==j)return 0;
int k=next[j]-1;
if(p[j0]==p[k+1])return k+2;
else return produceNext(p,j0,k+1,next);
}
//其实上面的递归函数纯属多此一举,按照上面的分析流程,用递推实现即可
int produceNext2(char *p,int j0,int *next)
{
int k,j=j0;
while(j>0)
{
k=next[j]-1;
if(p[j0]==p[k+1])return k+2;
else j=k+1;
}
return 0;
}
//KMP算法得到next(j) 个人版
void recursiveGetNext(char *p,int lengthP,int * next)
{
next[0]=-1;
int j=1;
for(;j<lengthP;++j)
next[j]=produceNext2(p,j-1,next);
}
int main()
{
char p[] = "aaaaaabbbbb";
int lengthP = strlen(p);
printf("String: %s\n",p);
printf("Length:%d\n",lengthP);
int * next = (int *)malloc(lengthP);
printf("Official version:\n");
getNext(p,lengthP,next);
int i;
for(i=0;i<lengthP;++i)
{
printf("%d ",next[i]);
next[i]=0;
}
printf("\nPersonal version:\n");
recursiveGetNext(p,lengthP,next);
for(i=0;i<lengthP;++i)
{
printf("%d ",next[i]);
}
free(next);
return 0;
}
*****Men Pass Away But Their Deeds Abide.*****

浙公网安备 33010602011771号