目录
个人理解
看了许多求nextval的文章,明明很简单的东西,非要描述得天花乱坠,里面也有许多错误思想。后来还是去看《数据结构》来得稳妥:
在我们求得的next中,有着许多重复无用的回溯值,比如next[j=2\3\4]时,它们需要回溯的都是a,那么为什么我们不直接定位到next[1]位置上呢?这样我们把所有相同的字符都替换掉,就可以节约出判断失败时的回溯时间。
多看几个例子,观察一下,也可以看《数据结构 C语言版》97页:
计算next链接
计算nextval函数代码
void get_nextval(char* TS, char* next, int len)
{
int i=1,j=0;
next[1]=0;
next[0]=-1;
while(i<len)
{
if(j==0||TS[i]==TS[j])
// 1 0
{
i++; j++;
if(TS[i]!=TS[j])next[i]=j;
else next[i]=next[j];
}
else{ j=next[j]; }
}
i=0; //打印next值
while(i<len)
printf("%d ", next[i++]);
printf(":nextval\n");
}
完整代码-VS2019
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void scan_position(char* TS, char* c, char* next);
void get_nextval(char* TS, char* nextval, int len);
int main()
{
char c[]="abababcabab"; //查找的子串
char T[]="ababacbaacbbabababababcabab"; //主串
int len=strlen(c);
char *nextval=(char *) malloc(len+1);
if(nextval==NULL)
printf("request Error\r\n");//申请空间失败
get_nextval(c, nextval, len); //获取next值
scan_position(T, c, nextval); //查找主串中是否有子串
free(nextval);
return 0;
}
void get_nextval(char* TS, char* nextval, int len)
{
int i=1,j=0;
nextval[1]=0;
nextval[0]=-1;
while(i<len)
{
if(j==0||TS[i]==TS[j])
// 1 0
{
i++; j++;
if(TS[i]!=TS[j])nextval[i]=j;
else nextval[i]=nextval[j];
}
else{ j=nextval[j]; }
}
i=0; //打印next值
while(i<len)
printf("%d ", nextval[i++]);
printf(":nextval\n");
}
void scan_position(char* TS, char* c, char* next)
{
int i=0,j=0;
int len=strlen(TS);
int clen=strlen(c);
char *str=NULL;
while(i<len&&j<clen)
{
if(j==-1||TS[i]==c[j])
{
i++,j++;
}else{
j = next[j];
}
}
str=(char*)malloc(clen); //结果输出
if(j!=clen) printf("'%s'中没有找到'%s'\r\n", TS, c);
else{
memcpy(str, TS+i-j, j);
printf("T:%d %s\r\n", i-j, str);
}
free(str);
}