再看此篇文章之前,建议先看下我写的上一篇文章,这样确保文章连贯性,更易理解本章内容。KMP算法——解决字符串匹配问题-CSDN博客
1.next数组的实现
sub是模拟串,lensub是模拟串长度
void GetNext(char*sub,int *next,int lensub)
{
next[0]=-1;
next[1]=0//由于下标为1的前面只有一个字母,所以无论模拟串是什么next[1]永远等于0
int i=2;//表示当前位置下标,0,1下标已经赋值
int k=0//记录当前位置的前一位置的next的值
while(i<lensub)
{
if(sub[i-1]==sub[k]||k==-1)
{
next[i]=k+1;//上述条件说明sub[0]~sub[k]=sub[i-k]~sub[i-1]所以当前位置之前的最长前后缀长度比前一位置的最长前后缀长度还多1;
i++;
k++;
}
else
{
k=next[k];//如果不相等就将k一直回退直到找到相等的位置为止
//但是我们思考下如果一直不相等,此时k会一直回退到0,然后还是不相等,执行k=next[k],k不就变成-1了吗,这个时候在进行循环上面if语句里的sub[k]不就越界访问了吗?所以对于这种特殊情况我们还要特别考虑在上面if语句里加一个条件k==-1
}
}
}
2.KMP[算法实现
这里说明下KMP算法返回的是主串中与模拟串的匹配的字符串中首字母的下标
str表示主串,sub表示模拟串,pos表示开始匹配的位置
int KMP(char*str,char*sub,int pos)
{
assert(str!=NULL&&sub!=NULL)
int lenstr==strlen(str);
int lensub=strlen(sub);
if(lensub==0||lenstr==0) return -1;
if(pos<0||pos>lenstr) return -1;
int *next=(int *)malloc(sizeof(int)*lensub);
assert(next);
GetNext(sub,next,lensub);//调用上面实现的函数,得到next数组里的值;
int i=pos;//用来遍历主串
int j=0;//用来遍历模拟串
while(i<lenstr&&j<lensub)
{
if(str[i]==sub[j]||j==-1)//匹配成功就继续向后遍历
{
i++;
j++;
}
else
j=next[j]//不匹配就将j回退到相应位置
//这里同上面next实现函数存在同样的一个问题,那就是如果主串和匹配串一直不匹配,导致j一直回退,最后变成-1也会造成越界访问,所以在这里上面的if语句也要加一个条件j==-1
}
if(j>=lensub)//表示不是因为遍历完整条主串退出循环的说明主串里面存在与模拟串匹配的串
return i-j;//i是主串中匹配到的串的最后一个字母的下标,j此时刚好等于模拟串长度
return -1;
}
3.next数组优化实现nextval
这里next数组的优化就在next实现函数中的末尾,用for循环从下标为1位置开始遍历判断想不相等,在对其进行相应处理就行,可以自己去尝试代码实现以下。
好了,以上两章就是关于KMP算法的全部内容,希望对你的编程道路有所帮助