【算法】KMP字符串匹配算法

目录

一、暴力

二、KMP

2.1 思路

2.2 next数组

2.3 实现

2.4 例题


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

一、暴力

在进行字符串匹配时,暴力匹配是我们想到的最简单的方法,即将子串与主串当中的每一个子串进行匹配。如果当前子串不匹配,则回溯到主串中下一个子串的开头重新进行匹配

在最坏的情况下,暴力匹配的时间复杂度为O(N*M),N为主串长度,M为子串长度


二、KMP

2.1 思路

在上面的例子中我们可以注意到,在子串中,不匹配的字符'C'前面的子串似乎有一些规律

可以看到,这部分子串的前缀后缀是相同的。如果我们能够将前缀移动到后缀的位置,是不是就能避免重复的比较了呢?

解释一下字符串的前缀和后缀:前缀就是从字符串开头到任意位置的一段字符串,后缀就是从字符串任意位置到字符串结尾的一段字符串

可以看到,通过这种方式,上面的箭头不需要向前回溯,下面的箭头也不需要回到子串的开头了,时间复杂度变为线性。这就是KMP算法的核心思想

但是我们怎样才能知道子串中每个位置的最长相同前后缀长度呢?这里就需要一个数组来维护了

2.2 next数组

next数组用于存放以下标i为结尾的子串最长相同前后缀长度,例如:

以下标0为结尾的子串"A",只有自己一个字符,因此最长相同前后缀长度为0(此处前后缀不能为子串自身)

在代码实现中,我们可以用一个f和i,f代表最长相同前缀结尾位置,i代表最长相同后缀结尾位置

以下标1为结尾的子串"AB",子串[f]和子串[i]不相同,且f=0,因此最长相同前后缀长度为0,i向后移动

以下标2为结尾的子串"ABA",子串[f]和子串[i]相同,有最长相同前后缀"A",因此最长相同前后缀长度为1,f和i都向后移动

以下标3为结尾的子串"ABAB",子串[f]和子串[i]相同,加上上一步的结果,有最长相同前后缀"AB",因此最长相同前后缀长度为2,f和i都向后移动

以下标4为结尾的子串"ABABC",此时子串[f]和子串[i]不同,f回到next[f-1]下标处

此时f=0,但子串[f]和子串[i]还是不同,因此最长相同前后缀长度为0。i到达子串结尾,结束匹配

构建next数组的代码如下:

int ne[N];void buildNext(string &p)
{int front = 0; //front为最长相同前缀结尾int i = 1; //i为最长相同后缀结尾while(i < n){if(p[i] == p[front]) //前后缀结尾字符相同{ front++; //front后移ne[i] = front; //front++后,值正好为最长相同前后缀长度i++; //i后移}else //字符不相同{if(front == 0) //front在子串开头{ne[i] = 0; //最长相同前后缀长度为0i++; //i后移}elsefront = ne[front-1]; //修改front位置}}
}

2.3 实现

有了next数组,剩下的步骤也很简单:

当字符不匹配时

若j不在子串开头,则按照next[j-1]的数值修改j的位置,例如此处next[j-1]为2。某些情况中,在比较子串的第一个字符(j=0)时就已经不匹配了,此时不需要移动j,将i后移即可

于是将j移动到下标为2处,继续进行匹配。当字符匹配时,i和j各自后移即可

当j移动到子串结尾,说明子串匹配成功

2.4 例题

观察样例中可以发现,主串中可能存在多个与子串相同的字符串,我们需要把所有相同子串的起始位置都输出出来

#include <iostream>
#include <string>
#include <vector>
using namespace std;const int N = 100010;
const int M = 1000010;int ne[N]; //next数组
int n, m;void buildNext(string &p) //构建next数组
{int front = 0;int i = 1;while(i < n){if(p[i] == p[front]){front++;ne[i] = front;i++;}else{if(front == 0){ne[i] = 0;i++;}elsefront = ne[front-1];}}
}int main()
{string p;string s;cin >> n >> p >> m >> s;buildNext(p);vector<int> ans;int i = 0, j = 0;while(i < m) //当i没走到主串结尾时{if(s[i] == p[j]) i++, j++; //字符匹配,i、j后移else if(j > 0) j = ne[j-1]; //字符不匹配且j不在开头,根据ne数组修改位置else i++; //字符不匹配且j在开头,i后移if(j == n) //j走到子串结尾,说明子串匹配成功{ans.push_back(i-j); //放入i-j即子串在主串中的起始位置j = ne[j-1]; //修改j进行下一轮匹配}}for(auto i : ans){cout << i << " ";}return 0;
}

完.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/57553.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

张雪峰:如果你现在是计算机专业,一定要优先报网络安全,它是未来国家发展的大方向

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 前言 “计算机专业 一定要优先报 网络安全 它是未来国家发展的大方向” 为什么推荐学网络安全&#xff1f; “没有网络安全就没有国家安全。”当前&#xff…

与ai一起作诗(《校园清廉韵》)

与ai对话犹如拷问自己的灵魂&#xff0c;与其说ai助力还不如说在和自己对话。 (笔记模板由python脚本于2024年10月19日 19:18:33创建&#xff0c;本篇笔记适合喜欢python和诗歌的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&…

知识点框架笔记3.0笔记

如果基础太差&#xff0c;搞不清基本交规的&#xff08;模考做不到60分&#xff09;&#xff0c;建议找肖肖或者小轩老师的课程看一遍&#xff0c;内容差不多&#xff08;上面有链接&#xff09;&#xff0c;笔记是基于肖肖和小轩老师的科目一课程以及公安部交管局法规&#xf…

w~自动驾驶合集9

我自己的原文哦~ https://blog.51cto.com/whaosoft/12320882 #自动驾驶数据集全面调研 自动驾驶技术在硬件和深度学习方法的最新进展中迅速发展&#xff0c;并展现出令人期待的性能。高质量的数据集对于开发可靠的自动驾驶算法至关重要。先前的数据集调研试图回顾这些数据集&…

[前端] ✨【如何用课程设计提升工程能力?】✨笔记

✨【如何用课程设计提升工程能力&#xff1f;】✨ &#x1f4da; 课程设计真的在语言工具类课程中占据了“C位”&#xff01;&#x1f451;设计得好的课程简直像一个实战训练营&#xff0c;既能帮助学生巩固理论&#xff0c;又能培养解决复杂问题的能力&#xff0c;还能让他们…

Redis --- 第六讲 --- 关于持久化

前言 持久化&#xff1a;MySQL的事务&#xff0c;有四大比较核心的特性 1、原子性 2、一致性 3、持久性 》 把数据存储到硬盘上 》持久&#xff0c;把数据存储在内存上》持久化。重启进程/重启主机之后&#xff0c;数据是否存在。 4、隔离性 Redis是一个内存数据库&#…

消息队列(仿RabbitMQ)—— 生产消费模型

本篇将实现一个3000多行的一个小项目&#xff0c;基于AMQP&#xff08;高级消息队列协议&#xff09;的消息队列&#xff0c;主要仿照 RabbitMQ 实现该代码&#xff0c;其本质也是生产消费模型的一个升级版本。实现的功能为&#xff1a;消息发布端将消息发送到服务器端&#xf…

如何开启华为交换机 http

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目…

腾讯 C++ 客户端一面,居然遇见了一道简单题。它怎么用go、C++解决

腾讯是目前全国最强的互联网公司之一&#xff0c;它有很好的福利尤其是能给应届生不错的工资待遇。 也正因如此&#xff0c;想进入腾讯工作的难度和竞争的激烈程度非常之大。 虽然感觉腾讯像是更看重个人综合能力的一家公司&#xff0c;算法题的好坏占面评比相对小些 但是竞争…

二、Linux 系统命令

一、系统命令 # 清屏 (Ctrl L) $ clear# 退出登录 $ exit # 历史命令 $ history $ history | grep java -jar 1. 系统信息 # 查看版本&#xff0c;当前操作系统发行版信息 $ cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) # 查看操作系统位数 $ getco…

【2022工业3D异常检测文献】Patch+FPFH: 结合3D手工点云描述符和颜色特征的异常检测方法

AN EMPIRICAL INVESTIGATION OF 3D ANOMALY DETECTION AND SEGMENTATION 1、Background PatchCore 方法&#xff1a; PatchCore是一种基于2D图像的异常检测方法&#xff0c;它使用预训练的深度学习模型&#xff08;如在ImageNet上预训练的模型&#xff09;来提取图像的局部特…

Memory Bus in SOC

在 SoC架构设计中&#xff0c;Memory Bus 是一个关键的组成部分&#xff0c;它负责连接 SoC 中的各个模块&#xff08;如 CPU、GPU、DMA、外设等&#xff09;与外部存储器&#xff08;如 DDR、NAND、Flash 等&#xff09;&#xff0c;起到连接处理器和存储器之间的桥梁作用&…

Qt优秀开源项目之二十四:EXCEL读写利器QXlsx

QXlsx是基于Qt5/Qt6的Excel文件&#xff08;*.xlsx&#xff09;的读写库。 github地址&#xff1a;https://github.com/QtExcel/QXlsx QXlsx既可以编译成库&#xff0c;也可以直接引用源码QXlsx-master\QXlsx\QXlsx.pri QXls提供了非常丰富的Examples&#xff0c;比如&#xff…

LED电子看板减少人工记录的错误

在当今快节奏的生产和管理环境中&#xff0c;准确性和效率是企业追求的关键目标。而传统的人工记录方式&#xff0c;常常因人为因素而出现各种错误&#xff0c;影响着企业的决策和运营。然而&#xff0c;随着科技的不断进步&#xff0c;LED 电子看板的出现为解决这一难题提供了…

无法获得下列许可 SOLIDWORKS Standard。 无法从使用许可服务器内读取数据,(-16,10009,10054)

无法获得下列许可 SOLIDWORKS Standard。 无法从使用许可服务器内读取数据&#xff0c;(-16,10009,10054) 错误如图 打开xxclean 扩展功能 服务无法启动

10.23Python_matplotlib_乱码问题

中英文问题解决方案 在使用 Matplotlib 绘图时&#xff0c;经常会出现中文字体显示问题。以下是一些解决方案&#xff1a; Windows 系统解决方案 在代码开始处添加以下代码&#xff0c;以支持中文显示&#xff1a; import matplotlib.pyplot as plt plt.rcParams[font.sans…

联想与Meta合作基于Llama大模型推出面向PC的个人AI智能体——AI Now | LeetTalk Daily...

“LeetTalk Daily”&#xff0c;每日科技前沿&#xff0c;由LeetTools AI精心筛选&#xff0c;为您带来最新鲜、最具洞察力的科技新闻。 联想集团昨日在美国西雅图召开年度Tech World大会。联想CEO杨元庆在主题演讲中&#xff0c;与Meta创始人兼CEO马克扎克伯格一道宣布&#x…

《15分钟轻松学Go》教程目录

在AI快速发展的时代&#xff0c;学习Go语言依然很有用。Go语言擅长处理高并发任务&#xff0c;也就是说可以同时处理很多请求&#xff0c;这对于需要快速响应的AI服务非常重要。另外&#xff0c;Go适合用来处理和传输大量数据&#xff0c;非常适合机器学习模型的数据预处理。 …

C++笔记---哈希表

1. 哈希的概念 哈希(hash)又称散列&#xff0c;是一种组织数据的方式。从译名来看&#xff0c;有散乱排列的意思。 本质就是通过哈希函数把关键字Key跟存储位置建立一个映射关系&#xff0c;查找时通过这个哈希函数计算出Key存储的位置&#xff0c;进行快速查找。 STL中的un…

【Python数据库操作】使用SQLite和MySQL进行数据存储和查询!

【Python数据库操作】使用SQLite和MySQL进行数据存储和查询&#xff01; 在现代应用程序中&#xff0c;数据存储与管理是至关重要的。Python为开发者提供了多种与数据库进行交互的方式&#xff0c;其中SQLite和MySQL是最常用的两种数据库。本文将深入探讨如何使用Python进行SQ…