next数组
next[i]表示使子串s[0···i]的前缀s[0···k]等于后缀s[i-k···i]的最大的k(前缀和后缀可以重叠,但不能是s[0···k]本身,当找不到相等的前后缀时令next[i]=-1(即next[i]是所求最长相等前后缀中前缀最后一位的下标)
用递归法求解next[i]:
void getNext(char s[],int len){//getNext求解长度为len的字符串s的next数组
int j=-1;
next[0]=-1;//初始化j=next[0]=-1
for(int i=1;i<len;i++){//求解next[1]~next[len-1]
while(j!=-1 && s[i]!=s[j+1]){//注意是&&
j=next[j];//反复令j=next[j]
}//知道j退回-1或s[i]==s[j+1]
if(s[i]==s[j+1]){//如果s[i]==s[j+1]
j++;//next[i]=j+1,先令j指向这个位置
}
next[i]=j;//令next[i]=j;
}
}
KMP算法中的next数组含义
(i指向text的当前欲比较位,j指向pattern中当前已匹配的最后位)
next数组的含义是当j+1位失败时,j应该退回的位置
KMP算法
bool KMP(char text[], char pattern[]) {//判断pattern是否为text的子串
int n = strlen(text), m = strlen(pattern);//求出字符串长度
getNext(pattern, m);//求出pattern的next数组
int j = -1;//初始化为-1,表示当前还没有任意一位被匹配
for (int i = 0; i < n; i++) {//试图匹配text[i]
while (j != -1 && text[i] != pattern[j + 1]) {
j = next[j];//不断回退,直到j回到-1或text[i]==pattern[j+1]
}
if (text[i] == pattern[j + 1]) {
j++;//text[i]与pattern[j+1]匹配成功,令j加一
}
if (j == m - 1) {//pattern完全匹配,说明pattern是text的子串
return true;
}
}
return false;//当执行玩text还未匹配成功时,说明pattern不是text的子串
}
统计文本串中模式串出现的次数
int KMP_num(char text[],char pattern[]){//统计pattern在text中出现的次数
int n=strlen(text),m=strlen(pattern);//字符串长度
getNext(pattern,m);//计算pattern的next数组
int ans=0,j=-1;//ans表示成功匹配次数,并初始化j为-1
for(int i=0;i<n;i++){//试图匹配text[i]
while(j!=-1&&text[i]!=pattern[j+1]){
j=next[j];//不断回退,直到j回到-1或text[i]==pattern[j+1]
}
if(text[i]==pattern[j+1]){
j++;//text[i]与pattern[j+1]匹配成功,令j加一
}
if(j==m-1){//pattern完全匹配,说明pattern是text的子串
ans++;//成功匹配次数加1
j=next[j];//让j回退到next[j]继续匹配
}
}
return ans;//返回成功匹配的次数
}
对KMP算法的优化
j回退无意义的问题出在pattern[j+1]==pattern[next[j]+1]上
nextval数组:不再是最长相等前后缀的含义,却让失配时处理最优
当模式串pattern的i+1位发生失配时,i应当退回的最佳位置
int KMP1_num(char text[],char pattern[]){//统计pattern在text中出现的次数
int n=strlen(text),m=strlen(pattern);//字符串长度
getNext(pattern,m);//计算pattern的next数组
int ans=0,j=-1;//ans表示成功匹配次数,并初始化j为-1
for(int i=0;i<n;i++){//试图匹配text[i]
while(j!=-1&&text[i]!=pattern[j+1]){
j=next[j];//不断回退,直到j回到-1或text[i]==pattern[j+1]
}
if(text[i]==pattern[j+1]){
j++;//text[i]与pattern[j+1]匹配成功,令j加一
}
if(j==m-1){//pattern完全匹配,说明pattern是text的子串
ans++;//成功匹配次数加1
j=next[j];//让j回退到next[j]继续匹配
}
}
return ans;//返回成功匹配的次数
}
本文详细介绍了KMP(Knuth-Morris-Pratt)算法中的next数组概念及其计算方法,包括递归法求解next数组的过程。KMP算法用于文本串中模式串的匹配,通过next数组实现高效回溯,避免不必要的字符比较。文章还讨论了next数组在匹配过程中的作用,以及如何利用nextval数组进一步优化匹配效率,提高查找模式串在文本串中出现次数的计算速度。
511

被折叠的 条评论
为什么被折叠?



