KMP算法
KMP算法是一个字符串算法,通常用于匹配字符串。
KMP算法的原理
如果我们暴力枚举下标 , 是文本串的下标, 是模式串(你要在文本串中匹配的字符串)的下标,时间复杂度 ,其中 分别为文本串和模式串的长度。
我们看一下匹配过程:(gif 动图请耐心观看)
时间复杂度高吧,出题人随便就 掉了。
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 文本串 | x | y | x | y | x | y | x | y | x | w |
| 模式串 | x | y | x | y | x | y | w | y |
咦?我们会发现 ,这样我们 匹配失败时可以跳 次(),就可以达到正确性和时间复杂度平衡的效果。
我们维护 表示s和s以i结尾的最长公共前后缀的长度,这样我们在 匹配失败时 可以直接跳到 。
维护 nxt[i]
若 也就是 匹配时,nxt[++i]=++j(其他同理写法也可以,最好固定一个写法),否则按文本串和模式串匹配失败来。
代码
nxt 数组的性质
nxt[i]既表示以i结尾的最长公共前后缀的长度,又表示 失配时跳跃的位置;nxt[i]越大,匹配的速度越慢,但至少移动 步;- 对于字符串 ,
nxt[]的最大下标s.size();
KMP算法应用
P3375 【模板】KMP
P4391 [BOI2009] Radio Transmission 无线传输
给你一个字符串 ,它是由某个字符串 不断自我连接形成的(保证至少重复 次)。但是字符串 是不确定的,现在只想知道它的最短长度是多少。
不想说过程,直接说结论:ans = n - nxt[n]
CF1200E Compress Words
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> s;
if (ans.empty())
ans = s;
else
{
int len = min(s.size(), ans.size());
string s1 = s.substr(0, len);
string s2 = ans.substr(ans.size() - len, len);
string s3 = s1 + "#" + s2;//中间必须拼上"#",不然有可能最长公共前后缀重合。
getNext(s3);
ans += s.substr(nxt[s3.size()]);
}
}
cout << ans;
CF126B Password
- 目标子串 一定是 的公共前后缀;
- 求出
nxt[]数组,并截取最长公共前后缀 ; - 在 范围内跑KMP,若找到 ,则 就是答案;
- 若
nxt[nxt[n]] != -1,则 即为答案;
P3435 [POI2006] OKR-Periods of Words
- 根据画图推导,对于 的每一个前缀 ,要找 的最短公共前后缀;
P4824 [USACO15FEB] Censoring S
- 删除 串之后产生的新的 串的起点一定在删除位置的左侧;
- 后出现 串先处理,考虑用栈维护;
- 栈中存储的下标维护已经匹配的 串的位数,
match[i];
P4591 [TJOI2018] 碱基序列
截止 年 月 日,此题难度 。
- 定义 表示前 个氨基酸可能的碱基序列以 结尾的可能的方案数;
- 答案为:;
- 状态转移方程:
dp[i][j+t.size()-1]=dp[i-1][j-1](这里我写的是哈希的); - 初始状态:
dp[0][i]=1。
__EOF__
本文作者:wbw121124
本文链接:https://www.cnblogs.com/wbw121124/p/18306182.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/wbw121124/p/18306182.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!

