【字符串】KMP
Algorithm
Task
给定一个文本串 和一个模式串 ,求 在 中出现的所有位置。
Limitations
要求时空复杂度均为线性。
Solution
回头重新学一遍看毛片 KMP 算法。
设 是一个字符串,则以下表述中, 代表 的第 个字符, 代表 的从 起到 结束的字串。
首先定义一个字符串的公共前后缀为这个字符串的一个 ,最长公共前后缀称为最长 。特别的,不认为字符串本身是自身的 。
性质:字符串 的 的 一定是 的 ,正确性显然。因此不断地跳最长 可以遍历字符串的所有
例如,对于字符串 来说,其唯一的 是 。
暴力匹配两个字符串,时间复杂度为 ,考虑优化这个算法。
假设当前匹配时 扫描到了第 位, 扫描到了第 位,且 从 向前 位组成的字符串与 的前 位相同,而 ,我们称为发生了失配。
考虑失配时,指针 不变,只有将指针 前移,才可能令下一位成功匹配。由于 不变,所以下一个可能发生匹配的字符串一定是 的某个前缀 满足
其中由于 是 的字串,一定有 。由于 的后 位与 的前 位匹配,又有 ,因此 的后 位一定与 的后 位即 匹配。得出
上面两个式子等量代换得到
由 的定义,我们发现 一定是 的 。根据 的性质,我们只需要不断的跳 的最长 即可找到一个最长的可以与 的后几位匹配的字串。因此问题转化为了如何求一个字符串 的所有前缀的最长 。
显然 。从第 位开始,我们发现问题等价于用 (模式串) 的一个前缀去匹配 (文本串)的一个后缀,求这个后缀最长是多少,而这个问题的解决方法与上面那个问题的方法 完 全 一 致,都是不断跳 即可。在 与 成功匹配时,记录 。而在这个问题中,由于 恒小于 ,正向扫描 时,所用到的 值都已经被计算出,因此可以得出正确的结果。
考虑时间复杂度:一个显然的事实是每次跳 模式串指针 都会至少减少 ,而当且仅当第 与第 匹配时, 才会自增,因此 仅增加了 ,因此 只可能减少 次,所以跳 的总次数不超过 ,而扫描整个文本串需要 的时间,因此总时间复杂度 。
Example
P3375 【模板】KMP字符串匹配
Description
给定一个文本串 和一个模式串 ,求 在 中出现的所有位置,同时要求输出 的每个前缀的 长度。
Limitations
字符串长度不超过
Solution
板板题
Code
#include <cstdio>
#include <cstring>
const int maxn = 1000006;
char S[maxn], T[maxn];
int nxt[maxn];
void KMP(char *A, char *B, int x, int y, const bool pt);
int main() {
freopen("1.in", "r", stdin);
scanf("%s\n%s", S + 1, T + 1);
int x = strlen(S + 1), y = strlen(T + 1);
KMP(T, T, y, y, false); KMP(S, T, x, y, true);
for (int i = 1; i <= y; ++i) {
qw(nxt[i], i == y ? '\n' : ' ', true);
}
return 0;
}
void KMP(char *A, char *B, int x, int y, const bool pt) {
for (int j = 0, i = pt ? 1 : 2; i <= x; ++i) {
while (j && (B[j+1] != A[i])) j = nxt[j];
if (B[j+1] == A[i]) ++j;
if (!pt) nxt[i] = j;
if (j == y) {
qw(i - y + 1, '\n', true);
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
2018-09-04 【数据结构】树链剖分