2026.5.24 数据结构 KMP算法实现

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <assert.h>

#include <memory.h>

int BF_Search(const char* MainStr, const char* SubStr)

{

//BF算法逻辑:

//1.申请两个指针i和j,分别指向主串和子串的开始位置

int i = 0;

int j = 0;

//"ABCD" strlen=4

//2.进入while循环,循环的条件是i和j还合法(换句话说就是还没有越界)

while (i < strlen(MainStr) && j < strlen(SubStr))

{

//3.比较i和j指向的字符,如果相同,则让i和j同步向后移动一个位置

if (MainStri == SubStrj)

{

i++;

j++;

}

//4.如果不相同,则让指向子串的j变量,回退到开始位置(0下标)

else

{

i = i - j + 1;

j = 0;

}

}

//5.如果while循环进不出,则说明查找结束了,只需要对j来做判断,就可以知道是否查找成功(j走出自身范围则找到,相反j未走出自身范围则没找到)

if (j < strlen(SubStr))

{

return -1;

}

return i - j;

}

//获取next数组

int* Get_Next(const char* SubStr)

{

//kmp求next数组的详细步骤(已知推未知) :

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

//5.进入while循环,循环条件是j合法(j最多指向倒数第二个字符)

while (j+1 < strlen(SubStr))

{

//9.如果一直比较失败,也就是NEX == -1了,则此时将NEX + 1变成0

// 赋值给下一个字符的next数组的位置

//6.用当前j指向的字符和其NEX保存的回退位置的字符进行比较

//7.如果相同,则让NEX + 1, 然后赋值给下一个字符的next数组位置

// (相当于将原本此时的左绿和右绿线末尾又各自了一个相同的字符,

// 所以左绿和右绿线共有长度 + 1)

if (NEX==-1 || SubStrj == SubStrNEX)

{

next++j = ++NEX;

}

//8.如果不相同,则让NEX去保存其回退位置字符的回退位置,接着比

// 较,直到比较成功,或者NEX触底(触底就是NEXT == -1)

else

{

NEX = nextNEX;

}

}

//10.当while循环退出,则next数组全部赋值完毕

return next;

}

int KMP_Search(const char* MainStr, const char* SubStr)

{

//BF算法逻辑:

//1.申请两个指针i和j,分别指向主串和子串的开始位置

int i = 0;

int j = 0;

//1.5 提供子串对应的next数组

int* next = Get_Next(SubStr);

//"ABCD" strlen=4

//2.进入while循环,循环的条件是i和j还合法(换句话说就是还没有越界)

while (i < (int)strlen(MainStr) && j < (int)strlen(SubStr))

{

//3.比较i和j指向的字符,如果相同,则让i和j同步向后移动一个位置

if (j == -1 || MainStri == SubStrj)

{

i++;

j++;

}

//4.如果不相同,则让指向子串的j变量,回退到开始位置(0下标)

else

{

//i打死不回退

j = nextj;//j回退到一个合适的位置

}

}

//5.如果while循环进不出,则说明查找结束了,只需要对j来做判断,就可以知道是否查找成功(j走出自身范围则找到,相反j未走出自身范围则没找到)

if (j < strlen(SubStr))

{

return -1;

}

return i - j;

}

//获取nextval数组

int* Get_Nextval(const char* SubStr)

{

int* next = Get_Next(SubStr);

int *nextval = (int*)malloc(strlen(SubStr) * sizeof(int));

if (NULL == nextval)

exit(EXIT_FAILURE);

nextval0 = -1;

for (int j = 1; j < strlen(SubStr); j++)

{

if (SubStrj != SubStrnext\[j])

nextvalj = nextj;

else

nextvalj = nextvalnext\[j];

}

free(next);

return nextval;

}

int KMP_Search2(const char* MainStr, const char* SubStr)

{

//BF算法逻辑:

//1.申请两个指针i和j,分别指向主串和子串的开始位置

int i = 0;

int j = 0;

//1.5 提供子串对应的next数组

int* nextval = Get_Nextval(SubStr);

//"ABCD" strlen=4

//2.进入while循环,循环的条件是i和j还合法(换句话说就是还没有越界)

while (i < (int)strlen(MainStr) && j < (int)strlen(SubStr))

{

//3.比较i和j指向的字符,如果相同,则让i和j同步向后移动一个位置

if (j == -1 || MainStri == SubStrj)

{

i++;

j++;

}

//4.如果不相同,则让指向子串的j变量,回退到开始位置(0下标)

else

{

//i打死不回退

j = nextvalj;//j回退到一个合适的位置

}

}

//5.如果while循环进不出,则说明查找结束了,只需要对j来做判断,就可以知道是否查找成功(j走出自身范围则找到,相反j未走出自身范围则没找到)

if (j < strlen(SubStr))

{

return -1;

}

return i - j;

}

int main()

{

/*const char* MainStr = "ABABCABCDABCDE";

const char* SubStr = "ABCD";*/

/*const char* MainStr = "AAAAAAAAAAB";

const char* SubStr = "AAAAAAAB";*/

//int index = BF_Search(MainStr, SubStr);

const char* MainStr = "ABCBAAABCDABCDE";

const char* SubStr = "ABCD";

//int index = KMP_Search(MainStr, SubStr);

int index = KMP_Search2(MainStr, SubStr);

if (index == -1)

{

printf("没找到\n");

}

else

{

printf("找到了,且在%d找到的\n", index);

}

return 0;

}

相关推荐
祖力5518 小时前
数据结构的基本概念与单向链表(链表数据类型构造、创建、头插、尾插、头删、尾删)
数据结构·链表
大明者省19 小时前
WSL2 Ubuntu22.04 GPU训练环境配置指南
人工智能·算法·计算机视觉
白狐_79821 小时前
408数据结构第8章:排序②——性质对比秒杀、场景选择与外部排序
java·数据结构·算法
zander25821 小时前
LeetCode 84:柱状图中的最大矩形——单调栈如何确定左右边界
java·数据结构·算法
Shell运维手记21 小时前
Linux 常用基础命令学习笔记
linux·运维·笔记·学习·算法·github
杨航 AI1 天前
O(n log n):线性对数原理拆解 这个是排序算法的黄金复杂度之一。
算法·排序算法
船厂电气自动化ai大模型1 天前
AI大模型与数学 第32课 函数凹凸性与二阶导数:拐点求解、凹凸区间计算(10道二阶导数计算题)
数据结构·人工智能·python·深度学习·算法
旖旎夜光1 天前
LeetCode 3:无重复字符的最长子串(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口
叠层归一研究院1 天前
AGI 系统(十一):二阶网络 — 二阶递归 × 多主体 (元符号网络)
开发语言·人工智能·算法·php·agi
zlinear数据采集卡1 天前
D223的PWM电机控制:6路独立脉冲+加减速算法深度解析
arm开发·stm32·嵌入式硬件·算法·fpga开发·架构