数据结构(KMP算法)

//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

next0 = -1;

next1 = 0;

//3 申请一个变量j指向当前最新的已知其next值的字符(初始化为1号下标)

int j = 1;

//4 再申请一个变量NEX 用来保存当前字符的失配时 可以看到的最长公共前后缀的共有长度(换句话说就是可以有多少个字符可以不用比较)

int NEX = nextj;

//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 || SubStrj == SubStrNEX)

{

next++j = ++NEX;

}

//8 如果不相同 则让NEX去保存其回退位置字符的回退位置 接着比较 直到比较成功 或者NEX触底(NEX==-1)

else

{

NEX = nextNEX;

}

//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);

nextval0 = -1;

int len1 = strlen(SubStr);

//3 申请变量j 让其从第二个字符开始向后遍历

for (int j = 1; j < len1; j++)

{

//5 如果j指向的字符和next数组变成的回退位置的字符不相同 则说明next数组保存的回退位置有效 直接照抄过来即可

if (SubStrnextval\[j] != SubStrnext\[j])

{

nextvalj=nextj;

}

//4 如果j指向的字符和next数组变成的回退位置的字符相同 则说明next数组保存的回退位置无效 直接将其回退位置字符的nextval对应值照抄过来

else

{

nextvalj = nextvalnext\[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||MainStri == SubStrj)

{

i++;

j++;

}

else

{

j = nextj;

}

}

if (j < SubStrlen)

{

return -1;

}

return i - j;

}

相关推荐
先吃饱再说35 分钟前
为什么堆能 O(log n) 插入?拆解完全二叉树的数组魔法
算法·排序算法
丘山望岳1 小时前
哈希——数据分类存储柜
数据结构·散列表
留白_1 小时前
【决策树】泰坦尼克号生存预测
算法·决策树·机器学习
hqzing1 小时前
鸿蒙 PC 底层开发技术详解(七):二进制自签名算法的实现
算法·华为·harmonyos
AI科技星1 小时前
超复数全域经济周期场与信息谱场——金融与密码学底层理论重构《0·1·∞三元一体全域超复数统一场论》系列全集(六一字不漏完整合订终版)
人工智能·算法·金融·密码学·拓扑学·乖乖数学·全域数学
AI科技星2 小时前
《01无穷全域信息场论:算子G与宇宙本体高维完备公理大典》
人工智能·python·算法·金融·乖乖数学·全域数学
Tim_102 小时前
【C++】013、空类占多少字节?
算法
Ricky_Theseus2 小时前
并查集:连通性问题
算法
Tairitsu_H3 小时前
[LC优选算法#18] 前缀和 | 除⾃⾝以外数组的乘积 | 和为K的⼦数组 | 和可被K整除的⼦数组
算法·前缀和·哈希算法
凯瑟琳.奥古斯特3 小时前
力扣1008:前序重建BST
开发语言·c++·算法·leetcode·职场和发展