KMP 算法
写作时间:2023/1/30/16:33
1. KMP 算法是什么
-
问题:
给出两个字符串 和 ,若 的区间 子串与 完全相同,则称 在 中出现了,其出现位置为 。
定义一个字符串 的 border 为 的一个非 本身的子串 ,满足 既是 的前缀,又是 的后缀。
现在请你求出 在 中所有出现的位置。对于 ,你还需要求出对于其每个前缀 的最长 border 的长度。 -
KMP 可以在 的时间内解决如上的字符串匹配的问题。( 分别是两个字符串的长度)
2. 关于 nxt 数组
2.1 定义
对于字符串 , 表示 : 中最长的相等真前缀与真后缀的长度。(根据定义即可发现,)
例如,对于 , 。(ps. 数组其实对应的就是 )
2.2 引理※
-
引理 1:(对于 ) 所对应的相等真前缀与真后缀是由 中的一个相等真前缀与真后缀扩展而来的,当然,不一定是由 中那个最长的相等真前缀与真后缀扩展而来的。
-
引理 2:, , ....,分别对应 中所有相等真前缀与真后缀的依次递减的长度。※
2.2 nxt[i] 怎么求?
首先,假设我们已知 。
根据引理 1, 有这样一个思路:枚举所有 的相等真前缀与真后缀,枚举顺序是按长度依次递减。设当前枚举到的相等真前后缀的长度是 , 若发现可以扩展,即 , 则 就是 的答案。
至于怎么枚举所有 的相等真前后缀,根据引理 2, 可知,... 构成了所有 的相等真前后缀长度。又因为 且我们已知 , 所以我们知道 ...
求 nxt 数组的代码
void getnxt(){
for(int i = 1; i <= n; i++) nxt[i] = 0;
nxt[0] = -1;
for(int i = 2, j; i <= n; i++){
j = nxt[i - 1];
while(a[j + 1] != a[i] && j != -1) j = nxt[j];
if(j != -1) nxt[i] = j + 1;
}
}
有了 数组,接下来就是利用 数组解决匹配问题。
(先说明一下,后面提到的 是文本串, 是模式串, 分别是 与 的长度)
3. KMP 算法流程
现在有两个指针 ,, 分别表示 当前要匹配 , 。接下来,分类讨论。
-
- :记录答案,
j = nxt[j] + 1; i++;
(中间直接跳过※) - :
i++; j++;
- :记录答案,
-
- :
i++; j++;
- :
j = nxt[j - 1] + 1;
- :
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!