算法学习笔记【1】:KMP 算法
实际上这个算法很早就学了,但是那个时候并没有了解的很清晰。 搞得好像现在有似的
首先,KMP 是三个人的名字。。。
首先,KMP 算法是用于字符串匹配的,时间复杂度为 O(n+m)O(n+m)O(n+m) [1]^{[1]}[1]。
Part 0:KMP 算法的诞生(可跳过)
我们假设有两个字符串 s1s_1s1,s2s_2s2,其中 s1s_1s1 为模式串,s2s_2s2 为文本串。
首先我们考虑普通查找算法的时间复杂度,最坏会被卡到 O(nm)O(nm)O(nm)
为什么会这么慢?
加入我们的 s1s_1s1,s2s_2s2 长这样 [2]^{[2]}[2]:
abababcabaa
ababcabaa
当 i=5i=5i=5 而 j=5j=5j=5 时,jjj 会直接跳回到 111,但是显然,跳到 333 会更加快速,那么我该怎么让电脑知道这个 jjj 跳到这里也行呢~
KMP 算法横空出世!
使用 KMP 算法即可解决
Part 1:KMP 算法的思路
KMP 算法的精髓就在于一个数组 kmpkmpkmp 上。
这个数组可以记录下当失配时 jjj 要跳到的地方。
这样就可以方便快速的“智能”选择。
那么匹配就变得十分简单:【见下文 Part 2】
请读者自行理解 kmpkmpkmp 数组的含义
那么 kmpkmpkmp 数组有什么含义?
注:此处的 i,j 含义与一般情况下不同
kmpkmpkmp 数组可以记录下模式串在第 1−j1-j1−j 的位置中的最长的真前缀与真后缀相同的长度。
如此,我们就可以实现回跳时可以跳到最后的位置,以便继续匹配。
接下来,我们就需要思考如何求出 kmpkmpkmp 数组。
这里我们考虑一个骚操作:自己匹配自己。
代码见下文 Part 2
然后就结果了。
Part 2:Code
首先放代码(洛谷 P3375 【模板】KMP字符串匹配):
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,m,kmp[N];//kmp 数组,懂得都懂
char s1[N],s2[N];
int main(){scanf("%s%s",s1+1,s2+1);n=strlen(s1+1),m=strlen(s2+1);int j=0;
//kmp begin
emm 这个只是我自己写代码的注释
//这个就是自己匹配自己的操作for(int i=2;i<=m;i++){while(j&&s2[j+1]!=s2[i])j=kmp[j];if(s2[j+1]==s2[i])j++;kmp[i]=j;}
//匹配文本串j=0;for(int i=1;i<=n;i++){while(j&&s2[j+1]!=s1[i])j=kmp[j];if(s2[j+1]==s1[i]){j++;if(j==m)cout<<i-m+1<<endl,j=kmp[j];}}for(int i=1;i<=m;i++)cout<<kmp[i]<<' ';
//主要懒得写注释
//kmp endreturn 0;
}
Part 3: 时间复杂度分析
众所周知,显然,复杂度是 O(n+m)O(n+m)O(n+m)。
其实很简单,因为 jjj 所进行的自增的次数不可能超过 mmm,因为 每次最多自增 111,会跳又不可能跳到比 000 更小,所以就只跳 n+mn+mn+m 次。
注:
[1]本文中 nnn,mmm 分别代表模式串和文本串的长度,同时 iii 表示文本串的索引,jjj 表示模式串的索引;
[2]此处的字符串借鉴了此文章:link;
算法学习笔记【1】:KMP 算法相关推荐
- 机器学习入门 —— 超级详细的KNN算法学习笔记、KNN算法的三要素、KNN算法的优缺点
文章目录 KNN(K nearest neighbors) K值的选择和影响 k取值偏小 k取值偏大 样本点距离的计算方式 闵可夫斯基距离 曼哈顿距离 欧几里得距离 切比雪夫距离 余弦距离 决策函数的 ...
- 【算法学习笔记】19.算法设计初步 最大子列和问题的几种方法
第一种就是纯粹的暴力枚举起始.终点. O(n^3) 第二种在第一种的基础上先进行初始化,将以第一个元素为起点,所有元素为终点的所有子列和存储在S数组中,所以在第三层循环中计算子列和是直接用S[j]-S ...
- 数据结构与算法 学习笔记(5):字符串
数据结构与算法 学习笔记(5)- 字符串 本次笔记记录了LeetCode中关于字符串的一些问题,并给出了相应的思路说明和代码.题目编号与LeetCode对应,方便查找. 题目1:LeetCode 13 ...
- 大顶堆删除最大值_算法学习笔记(47): 二叉堆
堆(Heap)是一类数据结构,它们拥有树状结构,且能够保证父节点比子节点大(或小).当根节点保存堆中最大值时,称为大根堆:反之,则称为小根堆. 二叉堆(Binary Heap)是最简单.常用的堆,是一 ...
- GMM高斯混合模型学习笔记(EM算法求解)
提出混合模型主要是为了能更好地近似一些较复杂的样本分布,通过不断添加component个数,能够随意地逼近不论什么连续的概率分布.所以我们觉得不论什么样本分布都能够用混合模型来建模.由于高斯函数具有一 ...
- Manacher算法学习笔记 | LeetCode#5
Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...
- 数据结构与算法学习笔记之 从0编号的数组
数据结构与算法学习笔记之 从0编号的数组 前言 数组看似简单,但掌握精髓的却没有多少:他既是编程语言中的数据类型,又是最基础的数据结构: 一个小问题: 为什么数据要从0开始编号,而不是 从1开始呢? ...
- 输出dag的所有拓扑排序序列_算法学习笔记(53): 拓扑排序
拓扑排序是对DAG(有向无环图)上的节点进行排序,使得对于每一条有向边 , 都在 之前出现.简单地说,是在不破坏节点 先后顺序的前提下,把DAG拉成一条链.如果以游戏中的科技树(虽然名字带树,其实常常 ...
- 算法学习笔记:对指定金额计算最少钞票数
算法学习笔记:对指定金额计算最少钞票数 一.引出问题 财务人员给员工发工资时经常遇到这样一个问题,即根据每个人的工资额(以元作为单位)计算出各种面值的钞票的张数,且要求总张数最少.例如,某职工工资为3 ...
最新文章
- 27_Notification
- vsphere中虚机的cpu热插拔和内存热添加
- 2013年1月21日记事
- 1.14 java内部类是什么鬼东西
- hdu1053 Entropy hdu2527 Safe Or Unsafe
- Vue 组件的自定义事件
- 浅谈“be practical and realistic”
- 【遗传算法】基于改进的遗传和粒子群算法求解高斯烟羽模型气体扩散优化问题含Matlab源码
- java简历中的项目经验怎么写_java软件工程师简历中项目经验怎么写?
- 批处理之for /r
- spring boot 报 http 406多种原因问题解决的总结
- 概率论由相关性求数学期望和方差的公式_概率论笔记2--离散随机变量、数学期望和方差...
- 时序动作检测《BMN: Boundary-Matching Network for Temporal Action Proposal Generation》
- Ubuntu 更新glibc
- opop如何和计算机链接,oppo如何连接电脑
- 东京迪斯尼海洋乐园攻略_迪士尼乐园-软件工程师的观点
- Postfix 邮件服务 - roundcube webmail
- 虚拟许可服务器访问失败,星外虚拟主机访问被控出现Unspecified error解决方法
- IOC和AOP的常见面试题
- 电脑爱好者2012年全彩高清PDF
热门文章
- linux门禁软件,基于ARM9与Linux的门禁监控系统软件设计
- java1.7 apk 签名_【keytool jarsigner工具的使用】Android 使用JDK1.7的工具 
进行APK文件的签名,以及keystore文件的使用...
- 苹果x电池容量_苹果iPhone X电池老化严重:越来越多用户收到性能劣化影响
- level 1与level 2的区别
- 山东大学单片机原理与应用实验 4.1 按键声光报警实验
- JavaScript语句
- 编程实用工具大全(二)(前后端皆可用,不来看看?)
- 负边距在布局中的使用 BY:色拉油啊油
- 转载 tiny6410 使用rt5370 usb无线网卡
- Colab 上使用shutil.copytree()复制整个文件夹到另一个文件夹