KMP算法
1、总结
切记:书上过程是下标从1开始的。不要纠结next数组第一位为什么是0。(DP也不纠结边界为啥是0啊。。。)。
- 完整过程:
- 求PM[]。(部分匹配表)
- 求move[]。(要移动的位数)
- 求next[]。(子串中移动后的下标)
- 简化过程:
- 求PM[]。
- 右移1位
- 加1(下标从1开始要加,下标从0开始不用加)
- 优化后的KMP
- 看程序,一步一步算。主串在后面,子串在前面。
2、代码
String数据结构
//串的堆分配存储结构(malloc()占用的是堆空间)
//下标为0的位置不用
typedef struct
{
char *ch; //若是非空串,则按串长分配存储区;否则ch为NULL
int length; //串长度
}HString;
typedef HString String;
2.1 计算next数组(下标从1开始)
//计算next数组
void get_next(String T, int next[])
{
int i = 1, j = 0;
next[1] = 0;
while (i < T.length) // i遍历串中的每个字符(主串)
{
if (j == 0 || T.ch[i] == T.ch[j]) //子串第一个元素失配||主串与子串指针处字符相同
{
++i;
++j;
next[i] = j;
// 1 子串第一个元素失配:主串下标为i的元素next值为1(next[i]=1)
// 1 第二次进while若还是子串第一个元素失配,则j=next[1]=0
// 1 第三次进while时执行与第一次进while时相同的操作:next[i]=1
// 2 主串i与子串j处字符相同:主串下标为i的元素next值为j+1
}
else //主串i与子串j处字符失配,且j不为0(j为1时来过渡一下)
j = next[j];
}
}
2.2 计算next数组(下标从0开始)
//计算next数组,下标0开始
void get_next_0(String T, int next[])
{
int i = 0, j = -1;
next[0] = -1;
while (i < T.length)
{
if (j == -1 || T.ch[i] == T.ch[j])
next[++i] = ++j;
else
j = next[j];
}
}
2.3 计算nextval数组(求next数组优化版)
//计算next数组-优化
void get_nextval(String T, int nextval[])
{
int i = 1, j = 0;
nextval[1] = 0;
while (i < T.length) // i遍历串中的每个字符(主串)
{
if (j == 0 || T.ch[i] == T.ch[j]) //子串第一个元素失配||主串与子串指针处字符相同
{
++i;
++j;
if (T.ch[i] != T.ch[j]) // i++,j++后,串与子串指针处字符不相同
nextval[i] = j;
else //主串与子串有连续两个字符相等
nextval[i] = nextval[j];
}
else //主串i与子串j处字符失配,且j不为0(j为1时来过渡一下)
j = nextval[j];
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】