6.7KMP算法
kpm用途:用于解决字符串模式匹配问题(求一个字符串(模式串)在另外一个字符串(主串)中的位置)。
字符串模式匹配问题暴力解法:
int Index(SString S,SString T){ //SString是存储字符串的结构,实际是一个字符数组,数组的第一个位置存储的是这个字符串的长度
int i=1,j=1; //主串和模式串下标指示器
while(i<=S[0]&&J<=T[0]){
if(S[i]==T[i]){
++i;
++j;
}
else{
i=i-j+2;j=1;
}
}
if(j>T[0])
return i-T[0];
else
return 0;
}
i=i-j+2由来:
时间复杂度:
kpm算法求解优点:可以把时间复杂度降到线性的数量级。
字符串前缀:字符串除了本身的的全部首部
字符串后缀:字符串除了本身的的全部尾部
最长公共前后缀长度:一个字符串相同的前后缀最长长度。
next数组:记录了模式串每个位置上发生匹配失败时,下一次和主串位置比对的字符的下标。
如何求next数组:
i是next数组下标计数器,j记录的的是next[i]的值;
@1
@2
@3
@4
求next数组代码:
void get_next(char T[],int next[]){ //基于递推的思想
i=1;
next[1]=0;
j=0;
while(i<T[0]){
if(j==0||T[i]=T[j]){
++i;
++j;
next[i]=j;
}
else j=next[j];
}
}
为什么加 j==0判断条件,并且加在那里:
Kmp算法代码:
int Kmp(char S[],cahr T[],int next[]){
int i=1;j=1;
while(i<=S[0]&&J<=T[0]){
if(j==0||S[i]==T[i]){
++i;
++j;
}
else{
j=next[j];
}
}
if(j>T[0])
return i-T[0];
else
return 0;
}
为什么加 j==0:
算法效率分析:
手动求解next数组的值:
1)写出字符串
2)标下标
3)求next数组值