前言
你好啊,我最近在学acwing的算法基础课,备战蓝桥杯,如果你也是一样的话,欢迎一起学习~
一、题目&解读
1、题目
二、思路
1、KMP是什么?
图片来源点击跳转
图中的移动位数 也就是构造next[i]
的过程了
2、思路
先想暴力怎么做,然后再进行优化
3、构造next[i]
看过上图的前缀和后缀,next[i]
的构造是找到前缀等于后缀的那个位置
构造next[i]=value
的例子
其中value
表示前缀和后缀相同的字母的数量
另外i
表示指针指到哪个元素下
代码实现
// 构造next数组
for (int i = 2, j = 0; i <= n;i ++) {
while (j && p[i] != p[j+1])
j = ne[j];// 对模式串进行匹配,如果没有匹配成功,j变成ne[j]的位置
if (p[i] == p[j+1])
j++;// 匹配成功,j到后一位
ne[i] = j;// 记录匹配成功的i位和j位的对应关系
}
4、匹配的过程
移动指针 找不同元素 图中比较s[7]
和p[6+1]
此时模板串的前缀 和 后缀 都和上面的相同 匹配完成
// 利用ne数组进行模式匹配
for (int i = 1, j = 0; i <= m;i ++) {
while (j && s[i] != p[j+1])
j = ne[j];// 没匹配成功, j变成ne[j]的位置
if (s[i] == p[j+1])
j ++;// 匹配成功,j往后一位
if (j == n) {
// 如果完全匹配完毕
printf("%d ", i - n);
j = ne[j];// 寻找p在s中的下一次出现的位置,利用ne数组优化时间复杂度
}
如果还是不懂 建议多刷几遍y总的讲解 y总,yyds!!
扫描二维码关注公众号,回复: 13712154 查看本文章
三、AC代码
时间复杂度 O(n+m)
#include <iostream>
using namespace std;
const int N = 1e5+10,M=1e6+10;
int n, m;
int ne[N];//ne表示next 建议不要起next 容易报错
char s[M], p[N];
int main () {
cin >> n >> p + 1 >> m >> s + 1;
// 对模板串构造 next 数组
for (int i = 2, j = 0; i <= n;i ++) {
while (j && p[i] != p[j+1])
j = ne[j];// 对模式串进行匹配,如果没有匹配成功,j变成ne[j]的位置
if (p[i] == p[j+1])
j++;// 匹配成功,j到后一位
ne[i] = j;// 记录匹配成功的i位和j位的对应关系
}
// 利用next数组对模式链匹配
for (int i = 1, j = 0; i <= m;i ++) {
while (j && s[i] != p[j+1])
j = ne[j];// 没匹配成功, j变成ne[j]的位置
if (s[i] == p[j+1])
j ++;// 匹配成功,j往后一位
if (j == n) {
// 如果完全匹配完毕
printf("%d ", i - n);
j = ne[j];// 寻找p在s中的下一次出现的位置,利用ne数组优化时间复杂度
}
}
return 0;
}
四、总结
学数据结构 最主要的还是要画图,先画一遍,代码自然就能够写了。
结尾:
感谢你能看完,希望对你有帮助 ,如有错误欢迎指正,码字不易,给个赞呗