KMP算法

KMP算法

一个人能走的多远不在于他在顺境时能走的多快,而在于他在逆境时多久能找到曾经的自己。

--- KMP

给定一个字符串S 以及一个模式串P

模式串P在字符串S中多次作为子串出现

求出模式串出现的下标

关键在于匹配不成功时不回退字符串S而是改变模式串继续匹配的位置来避免冗余操作。

我们通过这个例子先感受一下是next是什么

首先我们要知道前缀与后缀的概念

对于"aba"

前缀有 a ab aba

后缀有 a ba aba

对于S and P 两个字符串 如果在下标i处出现差异 这就意味着在1 到 i-1处是相同的

如果我们找到了最大的相等的前缀与后缀 我们就不必重新开始匹配而是借用已经匹配的有效片段继续进行

i 1 2 3 4 5 6

S a b a b a c

P a b a b a d

j 1 2 3 4 5 6

在下标6处不匹配 我们发现 在 1 - 5 a b a b a 最大相等的前缀与后缀是 a b a

那么接下来j 回退到3 再继续比较 i 则不用回退 仍然指向6 再比较Si Pj+1

我们可以这么想 好似平移 因为前缀与后缀相同 相当于是把P从前缀移动到了后缀再继续去比较(好吧确实有点抽象)

​ i

S a b a b a c

p a b a b a d

​ j

就类似这样 再去比较Si pJ+1 如果相同J++ 继续往后比 不同就再找上一个最大的前后缀

求next的做法与匹配过程相似 由于只有1个的时候的ne一定为0 我们从i = 2 开始 j = 0 因为我们每次比较的都Pi 和Pj+1

这个就相当于是拿前段 和后段去比较对比了 如果PI != PJ+1 j = nej 回到上一个前后缀相同的地方

1 2 3 4 5 6

a b a b a c

发现p6 != p3+1 j = nej = ne3 = 1

这样做的原因是我们已经知道了这个最大的前后缀已经没办法用了 因为下一个字母不再匹配 而我们的任务是要获得新的最大的前后缀 因此回退到上一个前后缀相同的地方 在这道题就是 a b a 这个相同的前后缀已经无法使用 我们只能回退到a这个前后缀 并判断PJ+1 是否与新加的字母相同,如果不相同 继续回退,最后J就是匹配的字母的数量 也就是最大的前后缀。

c++ 复制代码
#include <iostream>
#include <string>
using namespace std;
const int N = 100010;
char s[N] , p[N];
int ne[N];
int main(){
	int n , m; 
	cin >> n >> p+1 >> m >> s+1;
	//求ne数组
	for(int i = 2 , j = 0 ; i <= n ; i++){
		while(j && p[i] != p[j]) j = ne[j];
		if(p[i] == p[j+1]) j++;
		ne[i] = j;
	}
	//匹配KMP
	for(int i = 1 , j = 0 ; i <= n ; i++){
		while(j && s[i] != p[j+1]) j = ne[j];
		if(s[i] == p[j+1]) j++;
		if(j == n){
			cout << i - n << endl;
			j = ne[j] //找其他符合题意得
 		}
	}
	return 0;
}

j == n){

cout << i - n << endl;

j = nej //找其他符合题意得

}

}

return 0;

}

复制代码
相关推荐
reikocao1 小时前
卡尔曼滤波的动态机制:P如何改变融合权重
算法
总要学点什么2 小时前
第89篇:三维特效-螺旋圆效果——让螺旋臂卷起一圈圈外扩的涟漪
开发语言·javascript·ecmascript·webgl·cesium·空间分析·1024程序员节
漂流瓶jz2 小时前
UVA-1612 猜名次 题解答案代码 算法竞赛入门经典第二版
数据结构·算法·题解·排序·aoapc·算法竞赛入门经典
吞下星星的少年·-·2 小时前
Div.2 CF 1130B题(构造,贪心)
算法·贪心·构造
ShineWinsu3 小时前
对于Qt:QRadioButton常见属性以及QButtonGroup的解析
数据库·c++·qt·microsoft·gui·qradiobutton·qbuttongroup
傲世仙尊3 小时前
多态-虚表才活到运行期符号表早已消失
c++
开开心心_Every3 小时前
快速隐藏程序工具自定义快捷键一键切换
java·开发语言·前端·spring·智能手机·word·intellij-idea
chenbingjie_c3 小时前
C++ 多态完全指南:从虚函数重写到虚函数表原理
开发语言·c++
是main不是漫3 小时前
【双指针——移动零】数组划分类题目的入门基石
c++·算法