//KMP求next数组的详细步骤
//1 申请一个next数组 长度和字串长度一致
//2 将next数组的前俩个格子直接赋值-1和0
//3 申请一个变量j指向当前最新的已知其next值的字符(初始化为1号下标)
//4 再申请一个变量NEX 用来保存当前字符的失配时 可以看到的最长公共前后缀的共有长度(换句话说就是可以有多少个字符可以不用比较)
//5 进入while循环 循环条件是j合法 (j最多指向倒数第二个字符)
//6 用当前j指向的字符和其NEX保存的回退位置的字符进行比较
//7 如果相同 则让NEX+1 然后赋值给下一个字符的next数组位置 (相当于将原本此时的右绿和左绿线末尾又各自加了一个相同的字符 所以右绿和左绿的共有长度+1)
//8 如果不相同 则让NEX去保存其回退位置字符的回退位置 接着比较 直到比较成功 或者NEX触底(NEX==-1)
//9 如果一直比较失败 也就是NEX==-1,则此时将NEX+1变成0赋值给下一个字符的next数组的位置
//10 当while循环结束 则next数组全部赋值完成
//获取next数组
int* Get_Next(const char* SubStr)
{
//1 申请一个next数组 长度和字串长度一致
int* next = (int*)malloc(strlen(SubStr) * sizeof(int));
if (NULL == next)
exit(EXIT_FAILURE);
//2 将next数组的前俩个格子直接赋值-1和0
next[0] = -1;
next[1] = 0;
//3 申请一个变量j指向当前最新的已知其next值的字符(初始化为1号下标)
int j = 1;
//4 再申请一个变量NEX 用来保存当前字符的失配时 可以看到的最长公共前后缀的共有长度(换句话说就是可以有多少个字符可以不用比较)
int NEX = next[j];
//5 进入while循环 循环条件是j合法 (j最多指向倒数第二个字符)
while (j < +1 < strlen(SubStr))
{
//6 用当前j指向的字符和其NEX保存的回退位置的字符进行比较
//7 如果相同 则让NEX+1 然后赋值给下一个字符的next数组位置 (相当于将原本此时的右绿和左绿线末尾又各自加了一个相同的字符 所以右绿和左绿的共有长度+1)
//9 如果一直比较失败 也就是NEX==-1,则此时将NEX+1变成0赋值给下一个字符的next数组的位置
if (NEX == -1 || SubStr[j] == SubStr[NEX])
{
next[++j] = ++NEX;
}
//8 如果不相同 则让NEX去保存其回退位置字符的回退位置 接着比较 直到比较成功 或者NEX触底(NEX==-1)
else
{
NEX = next[NEX];
}
//10 当while循环结束 则next数组全部赋值完成
return next;
}
}
//next数组再次优化 得到next_well数组
//1 先搞出来next数组
//2 在申请一个nextval数组 并将其第一个格子赋值为-1
//3 申请变量j 让其从第二个字符开始向后遍历
//4 如果j指向的字符和next数组变成的回退位置的字符相同 则说明next数组保存的回退位置无效 直接将其回退位置字符的nextval对应值照抄过来
//5 如果j指向的字符和next数组变成的回退位置的字符不相同 则说明next数组保存的回退位置有效 直接照抄过来即可
int* Get_Nextval(const char* SubStr)
{
//1 先搞出来next数组
int* next = Get_Next(SubStr);
//2 在申请一个nextval数组 并将其第一个格子赋值为-1
int* nextval = (int*)malloc(strlen(SubStr) * sizeof(int));
if (NULL == nextval)
exit(EXIT_FAILURE);
nextval[0] = -1;
int len1 = strlen(SubStr);
//3 申请变量j 让其从第二个字符开始向后遍历
for (int j = 1; j < len1; j++)
{
//5 如果j指向的字符和next数组变成的回退位置的字符不相同 则说明next数组保存的回退位置有效 直接照抄过来即可
if (SubStr[nextval[j]] != SubStr[next[j]])
{
nextval[j]=next[j];
}
//4 如果j指向的字符和next数组变成的回退位置的字符相同 则说明next数组保存的回退位置无效 直接将其回退位置字符的nextval对应值照抄过来
else
{
nextval[j] = nextval[next[j]];
}
}
return nextval;
}
int KMP_Search(const char* MainStr, const char* SubStr)
{
assert(MainStr != NULL && SubStr != NULL);
int i = 0;
int j = 0;
int mainlen = strlen(MainStr);
int SubStrlen = strlen(SubStr);
int* next = Get_Next(SubStr);
while (i < (int)mainlen && j < (int)SubStrlen)
{
if (j==-1||MainStr[i] == SubStr[j])
{
i++;
j++;
}
else
{
j = next[j];
}
}
if (j < SubStrlen)
{
return -1;
}
return i - j;
}