模式匹配的一种改进算法–KMP算法
前言:
对于KMP算法我们需要清楚以下几点:
1、常规算法由于主串位置的回溯,导致匹配算法的最坏时间复杂度为O(m*n)
2、KMP算法的特点就是避免主串位置的回溯,通过next[j]函数值仅仅移动模式串的位置即可,它的时间复杂度位O(m+n)
3、next[j](j为模式串T的位序)通过递推求得,规定:
next[0]=0;
当T[j]=T[next[j]]时,next[j+1]=next[j]+1;当T[j]不等于T[next[j]]时,判断T[j]是否等于T[next[next[j]]],若等于,则next[j+1]=next[next[j]],依次往下递推
其余情况next[j]=1
4、next值得使用:若next[j]=0,则主串和模式串的位位置都向后移动一个位序,其余按照next[j]的值,只移动模式串的位序到next[j]所表示的值。
一、常规模式匹配算法
/*常规模式匹配 最坏情况下的时间复杂度是O(S[0]*T[0])*/
int indexO(SString S,SString T,int pos)
{
if (pos<1)
{
return 0;
}
int i=pos;
int j=1;
while(i<=S[0]&&j<=T[0])
{
if (S[i]==T[j])
{
i++;
j++;
}
else
{
i=i-j+2;
j=1;
}
}
if (j>T[0])
{
return i-T[0];//此处之所以没有-1,是因为匹配成功后,j比模式串的长度长1
}
else
return 0;
}
二、KMP算法
/*模式匹配的改进算法--KMP算法*/
int indexKMP(SString S,SString T,int pos,int next[])
{
if (pos<1)
{
return 0;
}
int i=pos;
int 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-StrLength(T);
}
else
return 0;
}
/*KMP算法之next函数*/
void KMP_next(SString T,int *next)
{
int i=1;//i是模式串的位序
next[1]=0;
int nexti=0;//j是i的next值
while(i<T[0])
{
if (nexti==0||T[i]==T[nexti])
{
i++;
nexti++;
next[i]=nexti;
}
else
{
nexti=next[nexti];
}
}
}