【算法模板】轻松学会KMP算法
目录
0.前言
1. 视频理解KMP的流程
2.代码实现
3.结束语
0.前言
KMP算法是在字符串中寻找字串的算法,时间复杂度为O(n)。
KMP算法中有两个关键因素:
- next数组
- 匹配机制
1. 视频理解KMP的流程
由于想把最好的资源分享给大家(绝对不是作图水平太低!,读者们可以在下面的视频中先行了解KMP算法,这也是作者最先了解KMP思想的视频:
https://www.bilibili.com/video/BV1AY4y157yL/?spm_id_from=333.337.search-card.all.click&vd_source=936e3852c850b5e76e4c4e91daa5dd95
如果大家看完视频后还在看这篇文章,那么下面就是对于KMP算法的具体实现。
2.代码实现
p1建议使用“cbcbc”这个字符串来带入理解。
p2建议使用“cbc”这个字符串来带入理解。
开始之前,我们需要知道字符串前后缀子串:
像这样,如果是奇数,那么前3个字符称为字符串的前缀,后面的CBA则是后缀。
ne数组的原理就是从第二个字符开始往后找。
字符串AB中,前缀A不等于前缀B,于是B在next数组中存的是0;
字符串ABC中,前缀A和 后缀C不同,于是C在next数组中存的是0;
以此类推~~~
char* my_strstr(const char* p1,const char* p2)
{//在 s 字符串中寻找 p 字符串char* s = p1 - 1; char* p = p2 - 1;//next数组 neint* ne = (int*)malloc(strlen(p2) * 4);//因为首字符没有前后缀子串ne[1] = 0;//next数组的创建for (int i = 2, j = 0; p[i]; i++){// j 代表了 目前正在匹配的字符的前一个字符 的下标。while (j && p[j + 1] != p[i]){//如果匹配失败,那么 j 作为下标将会回到 ne[j] 的位置j = ne[j];}//匹配成功,证明有相同的前后缀字串,j代表了相同的子串长度if (p[i] == p[j + 1]){j++;}//next数组中存放i位置时,相同的前后缀子串长度ne[i] = j;}//寻找字串for (int i = 1, j = 0; s[i]; i++){// j 代表了模板串的 已经匹配成功的 长度//匹配不成功就回撤继续匹配while (j && p[j + 1] != s[i]){j = ne[j];}//匹配成功,已经匹配成功的长度加1if (p[j + 1] == s[i]){j++;}//如果模板串已经匹配完最后一个字符,那么停止匹配,返回子串首字符地址if (j == strlen(p2)){// i - strlen(p2) 子串首字符距离p2的长度return p1 + i - strlen(p2);}}return NULL;
}
其实写在函数里多少有点影响KMP算法的功能,因为这个算法可以找到多处子串的起始位置。
所以可以考虑改造一下或则写在main函数中。
写在main函数中时,通常用字符数组来存字符串,这里说一下,字符串最好从下标为1的地址开始存。
#include <iostream>
#include <algorithm>
using namespace std;const int N = 1000100;//next数组
int ne[N];//在p中寻找子串s
char s[N],p[N];//字符串s的长度为m,字符串p的长度为n
int m,n;int main()
{cin >> n >> p + 1 >> m >> s + 1;//创建next数组for(int j = 0, i = 2; i <= n; i++){while(j && p[j + 1] != p[i]){j = ne[j];}if(p[i] == p[j+1]){j++;}ne[i] = j;}//开始匹配for(int i = 1,j = 0; i <= m; i++){while(j && s[i] != p[j + 1]){j = ne[j];}if(s[i] == p[j + 1]){j++;}if(j == n){//返回子串下标printf("%d ",i - n);j = ne[j];}}return 0;
}
3.结束语
KMP算法是比较难理解的一个算法,要多琢磨,建议数组储存数据时从下标1开始储存,这样会方便很多,本代码中让p1和p2减一也是为了实现 储存数据时从下标1开始储存。
另外,能用KMP算法解决的问题,同样也可以使用字符串哈希算法解决。有兴趣可以去了解一下。
【算法模板】轻松学会KMP算法相关推荐
- 【数据结构与算法】字符串匹配 KMP 算法
单模式串匹配 BF 算法和 RK 算法 BM 算法和 KMP 算法 多模式串匹配算法 Trie 树和 AC 自动机 KMP 算法 KMP 算法是根据三位作者(D.E.Knuth,J.H.Morris ...
- 最大流算法模板:EK和dinic算法
最大流算法模板:EK和dinic算法 一.EK算法模板 #include<iostream> #include<queue> using namespace std; cons ...
- 算法(2)KMP算法
1.0 问题描述 实现KMP算法查找字符串. 2.0 问题分析 "KMP算法"是对字符串查找"简单算法"的优化. 字符串查找"简单算法"是源 ...
- 算法:模式匹配之KMP算法
前言: 昨天看到<算法导论>里的第32章:字符串匹配,说到一个关于字符串匹配的很好的算法--KMP.关于KMP的内存含意以及KMP的来源,不是本文讲述的范畴,请感兴趣的读者自行查阅相关资料 ...
- kmp算法的c语言,KMP算法 纯C实现
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 我自己写的KMP算法: int nt[256]; void get_next1(char* T, int next[], int tlen) { int ...
- js实现kmp算法_字符串匹配算法KMP算法
数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多 ...
- c语言编程算法模板,C语言编程算法精选.doc
C语言编程算法精选 二级C语言编程算法精选一.数学计算1.编写函数double?fun功能是:根据公式计算s,计算结果通过形参指针sn传回:n通过形参传入.? ? 1? ?? ?1? ?? ? 1? ...
- 代码随想录算法训练营第八天|kmp算法
kmp题目链接 讲解直接看代码随想录就可以了,代码随想录 一.什么是前缀表 前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配. 那么什么是前 ...
- KMP算法详解P3375 【模板】KMP字符串匹配题解
KMP算法详解: KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt(雾)提出的. 对于字符串匹配问题(such as 问你在abababb中有多少个 ...
最新文章
- Java 小故事系列 导航
- NoMasp博客导读
- VMware + CentOS 网络设置为NAT模式
- windows 2012 如何设置取消禁拼ping
- c++ skia 判断jpg图片是完整的_python处理图片入门级
- [react] React15和16别支持IE几以上?
- 第11章 递归分形树(《Python趣味创意编程》教学视频)
- Facebook开源移动端深度学习加速框架,比TensorFlow Lite快一倍
- latex 导出的pdf生成书签 目录
- 计算机专业计算机二级java有用吗_计算机二级java含金量如何 对就业有帮助吗
- web前端开发技术实验与实践(读书笔记)
- iMeta | 南医大余光创组ggtree最新文章-系统发育树存储与可视化的数据结构
- 电脑和微信怎么发邮件到别人邮箱,企业邮箱如何发email给别人
- 机器人唱歌bgm_变形金刚5所有背景乐插曲盘点 长老机器人弹钢琴BGM是什么歌
- util是utiliy的缩写,意为多用途的,工具性质的包
- Kinect-Fusion解读
- AI工具究竟是帮手还是对手?你怎么看,一起来聊聊吧!
- mysql获取汉字拼音首字母_MySQL数据库获取汉字拼音的首字母函数
- 电脑开机自动登录,断网自动重连以及桌面联网小程序
- 程序员非机械键盘_最好的非机械键盘