用一篇文章来彻底搞懂KMP算法

简介: 用一篇文章来彻底搞懂KMP算法
秋名山码民的主页
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
🙏作者水平很有限,如果发现错误,一定要及时告知作者

@TOC


# 前言 KMP算法,对于刚开始学算法的人还是有一点的难度的,但是总体来说比较简单,本文的目的就是用**图文+代码**的形式来搞懂kmp算法,至于是否吹牛,还请你看下去! # 一、kmp算法是什么? 这是一个字符串匹配算法,对暴力的那种**一一比对**的方法进行了优化,使时间复杂度大大降低,如果要说kmp算法的时间复杂度是多少的话,O(m+n),至于为什么是这个,还请我用代码来进行分析,稍安。 命名还是和以前一样用3个外国人的名字首字母命名的, ## 本文中出现的基本概念 >s[ ],p[]是模式串,其中s为长,p为短 >部分匹配值:前缀和后缀的**最长共有元素的长度** >**next[ ]是“部分匹配值表”,即next数组,它存储的是每一个下标对应的“部分匹配值”** # 二、kmp算法 首先像往常一样,我们先来考虑如何用**BF算法**来解答字符串匹配的问题 ```cpp for (int i = 1; i <= n; i++) { bool flag = true; for (int j = 1; j <= m; j++) { if (s[i] != p[j])//匹配失败 { flag = false; break; } } } ``` 可以看出时间复杂度为O(n^2) **kmp** = next数组+匹配字符串 我们先来看比较重要的**next【】数组**究竟是什么东西? >对next[ j ] ,是p[ 1, j ]串中前缀和后缀相同的最大长度(部分匹配值),即 p[ 1, next[ j ] ] = p[ j - next[ j ] + 1, j ] ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/c7abe2aa951b4f07a067261e58faa673.png) 模拟上面的next数组。 >对next[ 1 ] :前缀 = 空集——后缀 = 空集—next[ 1 ] = 0; >对next[ 2 ] :前缀 = { a }——后缀 = { b }—next[ 2 ] = 0; >对next[ 3 ] :前缀 = { a , ab }——后缀 = { c , bc}—next[ 3 ] = 0; >对next[ 4 ] :前缀 = { a , ab , abc }——后缀 = { a . ca , bca }—next[ 4 ] = 1; >对next[ 5 ] :前缀 = { a , ab , abc , abca }—后缀 = { b , ab , cab , bcab}—next[ 5 ] = 2; ​ s串 和 p串都是从1开始的。i 从1开始,j 从0开始,每次s[ i ] 和p[ j + 1 ]比较 ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20b018d01c8f48ba80636a629918bcd4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56eL5ZCN5bGx56CB5rCR,size_19,color_FFFFFF,t_70,g_se,x_16) 当匹配到上图过程时候,**要移动p串(不是移动1格,而是直接移动到下次能匹配的位置)** ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/818290c3ad844aec9c573ef44921e3ad.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56eL5ZCN5bGx56CB5rCR,size_20,color_FFFFFF,t_70,g_se,x_16) # 代码解析 下面我们来看kmp的代码 ```cpp #include using namespace std; const int N = 100010; int n, m; int next[N]; char s[N], p[N]; //s为模式串, p为匹配串 int main() { cin >> n >> s + 1 >> m >> p + 1; //下标从1开始 //求next[]数组 for (int i = 2, j = 0; i <= m; i++) { while (j && p[i] != p[j + 1]) j = next[j]; //当j退无可退,或者二者匹配时候退出 if (p[i] == p[j + 1]) j++; next[i] = j; } //匹配操作 for (int i = 1, j = 0; i <= m; i++) { while (j && s[i] != p[j + 1]) j = next[j]; if (s[i] == p[j + 1]) j++; if (j == n) { printf("%d ", i - n);//打印 j = next[j]; } } return 0; } ``` 分析时间复杂度: >i循环m次,则j最多加了m次,所以看似是2个循环,实则时间复杂度为2m则O(N) # 总结 插个题外话,实际上kmp算法,更像是一次又一次的尝试,说好听点,各位彦祖想一下,假如你追女生的时候,一次失败了,再来一次,不行,像next[j]一样退一步,再战,如果成功了,那么是不是就能再进一步?
相关文章
|
2月前
|
算法
第四章 KMP算法理论基础
第四章 KMP算法理论基础
25 0
|
2月前
|
算法
KMP算法
KMP算法
43 0
|
4月前
|
算法 C++
A : DS串应用–KMP算法
这篇文章提供了KMP算法的C++实现,包括计算模式串的next数组和在主串中查找模式串位置的函数,用于演示KMP算法的基本应用。
|
5月前
|
数据采集 算法 JavaScript
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
JavaScript字符串搜索涵盖`indexOf`、`includes`及KMP算法。`indexOf`返回子字符串位置,`includes`检查是否包含子字符串。KMP是高效的搜索算法,尤其适合长模式匹配。示例展示了如何在数据采集(如网页爬虫)中使用这些方法,结合代理IP进行安全搜索。代码示例中,搜索百度新闻结果并检测是否含有特定字符串。学习这些技术能提升编程效率和性能。
142 1
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
|
4月前
|
算法
KMP算法
KMP算法
37 0
|
5月前
|
算法 搜索推荐
推荐系统,推荐算法01,是首页频道推荐,一个是文章相似结果推荐,用户物品画像构建就是用户喜欢看什么样的文章,打标签,文章画像就是有那些重要的词,用权重和向量表示,推荐架构和业务流
推荐系统,推荐算法01,是首页频道推荐,一个是文章相似结果推荐,用户物品画像构建就是用户喜欢看什么样的文章,打标签,文章画像就是有那些重要的词,用权重和向量表示,推荐架构和业务流
|
5月前
|
算法 Java
KMP算法详解及其在字符串匹配中的应用
KMP算法详解及其在字符串匹配中的应用
|
6月前
|
人工智能 算法 BI
一篇文章讲明白KMP算法(俗称看毛片算法)
一篇文章讲明白KMP算法(俗称看毛片算法)
67 0
|
4天前
|
机器学习/深度学习 算法
基于改进遗传优化的BP神经网络金融序列预测算法matlab仿真
本项目基于改进遗传优化的BP神经网络进行金融序列预测,使用MATLAB2022A实现。通过对比BP神经网络、遗传优化BP神经网络及改进遗传优化BP神经网络,展示了三者的误差和预测曲线差异。核心程序结合遗传算法(GA)与BP神经网络,利用GA优化BP网络的初始权重和阈值,提高预测精度。GA通过选择、交叉、变异操作迭代优化,防止局部收敛,增强模型对金融市场复杂性和不确定性的适应能力。
117 80
|
1天前
|
机器学习/深度学习 算法 索引
单目标问题的烟花优化算法求解matlab仿真,对比PSO和GA
本项目使用FW烟花优化算法求解单目标问题,并在MATLAB2022A中实现仿真,对比PSO和GA的性能。核心代码展示了适应度计算、火花生成及位置约束等关键步骤。最终通过收敛曲线对比三种算法的优化效果。烟花优化算法模拟烟花爆炸过程,探索搜索空间,寻找全局最优解,适用于复杂非线性问题。PSO和GA则分别适合快速收敛和大解空间的问题。参数调整和算法特性分析显示了各自的优势与局限。

热门文章

最新文章