数据结构:KMP算法
1.何为KMP算法
KMP算法是由Knuth、Morris和Pratt三位学者发明的,所以取了三位学者名字的首字母,叫作KMP算法。
2.KMP的用处
KMP主要用于字符串匹配的问题,主要思想是当出现字符串不匹配时,我们可以知道一部分之前已经匹配过的的文本内容,利用这些信息从而避免从头再开始匹配。
但是如何才能知道之前已经匹配过的内容呢?这是KMP算法的核心,也是KMP算法里面的next数组的用处。
3.最长相等前后缀
一个字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续字串
后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串
前缀表也就是next数组要求的是最长相等前后缀的长度,例如a的最长相等前后缀为0,aaa得到最长相等前后缀为2,aaba的最长相等前后缀为1。
4.next数组(前缀表)
KMP的核心就是next数组,当模板串和主串不匹配时,next数组是用来让模板串知道应该从哪里再开始匹配。
next数组记录下标i之前(包括i)的字符串中,有多大长度的相等前后缀。
这里借用了代码随想录的图片

比如我们要在文本串aabaabaafa中寻找模板串aabaaf,在b和f之前发现匹配不了,如果用暴力算法,就要从头开始匹配,文本串和模板串都需要进行回退,时间复杂度是很高的,但如果我们使用KMP算法,next数组记录了f之前有多大长度的相等前后缀,也就是我们知道了之前匹配过的内容,就会从上次已经匹配的内容开始匹配,这里为什么能这样呢?我是这样理解的:
文本串: aabaabaafa 用i遍历
模板串:aabaaf 用j遍历
在b和f时不相同了,这时候我们不想再匹配我们已经匹配过的,也就是说我们不想i回退,而是一直向前走,那我们就要j进行回退,回退到什么位置呢,前面已经匹配到了,说明已经匹配过的文本串aabaa中含有模板串一部分内容,又因为前后缀有相等的部分。所以我们回退到前后缀相等的前缀位置,因为和文本串是相同的,所以aabaa的后缀aa和文本串的aabaa的后缀aa是相等的,又有aabaa的前缀aa和后缀aa是相等前后缀,所以前缀aa和文本串aabaa的后缀aa相等,我们回退到aabaa的b即可避免再次匹配aabaa的前缀aa,这样也可以保证模板串aabaa的前缀aa是已经匹配过的。
f之前这部分的字符串(也就是字符串aabaa)的最长相等前后缀是aa ,因为找到了最长相等的前后缀,匹配失败的位置是后缀的后面,那么我们找到与其相同的前缀的后面重新匹配就可以了。
5.如何计算next数组
例如a a b a a f下标0 1 2 3 4 5next 0 1 0 1 2 0
当下标为0时,长度为前1个字符的字串a,最长相等前后缀的长度为0
当下标为1时,长度为前2个字符的字串aa,最长相等前后缀的长度为1
依次类比,可以得到next数组,也就是前缀表
可以看出模板串和next数组对应位置的数字表示的是下标i之前(包括i)的字符串中,有多大长度的最长相等前后缀。

当我们找到不匹配的位置时,就要看它前一个字符的next数组的值是多少,因为我们要找前面字符串的最长相等前后缀,所以要看前一位的next数组的值,前一个字符的next数组值为2,所以我们把下标j移动到2的位置继续匹配,这样就可以匹配到了。
6.next数组实现
主要是处理前后缀相等和不相等的情况,我们首先定义一个getNext函数来构造next数组,参数为指向next数组的指针,和一个字符串
void getNext(int* next,string& s)
接着我们对其进行初始化,定义两个指针i和j,j指向前缀末尾,i指向后缀末尾,对next数组进行初始化赋值
int j=0;
next[0]=j;
next[i]表示i(包括i)之前最长相等的前后缀长度,就是j,所以初始化next[0]=j
6.1前后缀不相同
j=0,所以我们从i=1开始,遍历文本串,就像这样
for(int i=0;i<s.size();i++)
j首先要保证是大于0的,因为下面j要回退,然后就是s[i]和s[j]的比较,如果s[i]和s[j]不相同,j就要找前一位对应的回退位置,因为这里j之前的前缀已经和i的后缀不相等了,所以我们就要j进行回退。
while(j>=0&&s[i]!=s[j])
{j=next[j-1];
}
6.2前后缀相同
如果是s[i]和s[j]相同,这时候只要同时移动i和j,这时候找到了相同的前后缀,我们要把j的值赋值给next[i],因为next[i]记录相同前后缀的长度
if(s[i]==s[j])
{j++;
}
next[i]=j;
完整代码如下:
void getNext(int* next, const string& s)
{int j = 0;next[0] = 0;for(int i = 1; i < s.size(); i++) {while (j > 0 && s[i] != s[j]){ j = next[j - 1]; }if (s[i] == s[j]){j++;}next[i] = j;}
}
7.例题 
void getNext(int* next,const string& s){int j=0;next[0]=0;for(int i=1;i<s.size();i++){while(j>0&&s[i]!=s[j]){j=next[j-1];}if(s[i]==s[j]){j++;}next[i]=j;}}int strStr(string haystack,string needle){if(needle.size()==0){return 0;}int next[needle.size()];getNext(next,needle);int j=0;for(int i=0;i<haystack.size();i++){while(j>0&&haystack[i]!=needle[j]){j=next[j-1];}if(haystack[i]==needle[j]){j++;}if(j==needle.size()){return (i-needle.size()+1) ;}}return -1;}
这道题很明显是字符串匹配的问题,所以我们使用KMP算法,首先是next数组的构建,这是模板,直接写就行,然后就是模板串和文本串的匹配,如果不相同,那j就回退到next[j-1],如果相同,j就直接向后移动即可,当j和模板串的长度相等时,此时i一定是大于等于模板串的长度的,因为i之前的文本串是包含模板串的,所以我们用i-模板串的长度+1就是第一个匹配项的下标了。
相关文章:
数据结构:KMP算法
1.何为KMP算法 KMP算法是由Knuth、Morris和Pratt三位学者发明的,所以取了三位学者名字的首字母,叫作KMP算法。 2.KMP的用处 KMP主要用于字符串匹配的问题,主要思想是当出现字符串不匹配时,我们可以知道一部分之前已经匹配过的的文…...
小程序真机如何清除订阅数据
在做小程序订阅消息开发的过程中发现,真机上如果是选择了‘总是保持以上选择’,一旦用户授权后,后面就不会再弹出申请改订阅消息的授权弹窗,这对于开发过程中是很不方便的。 曾试过清除缓存,重进小程序也不能清除掉 解…...
基于ssm出租车管理系统的设计与实现论文
摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本出租车管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息&…...
音视频转码
音视频转码是指: 容器中音视频数据编码方式转换,如由H.264编码转成mpeg-4编码,mp3转成AAC;音视频码率的转换,如4Mb视频码率降为2Mb,视频分辨率的转换,如1080P转换为720P,音频重采样…...
编解码异常分析
前言 最近在做的项目,有H264解码的需求。部分H264文件解码播放后,显示为绿屏或者花屏。 分析 如何确认是否是高通硬解码的问题 adb 指令 adb root adb remount adb shell setenforce 0 adb shell setprop vendor.gralloc.disable_ubwc 1 adb shell c…...
APISpace 热门好用的API推荐,含免费次数
短信验证码:可用于登录、注册、找回密码、支付认证等等应用场景。支持三大运营商,3秒可达,99.99%到达率,支持大容量高并发。通知短信:短信通知支持三大运营商以及虚拟运营商,我们提供电信级运维…...
Qt/QML编程学习之心得:一个.qml文件调用另一个.qml文件(十七)
在c++中,一个文件调用另外一个文件最直接最快捷的方式就是#incldue<头文件>的使用,那么在元数据描述性语言QML中,如何从一个界面描述调用另外一个界面描述,一个.qml文件调用另外一个.qml呢?QML虽然有个import,但是用法可以说完全不同于#include。 引用方法1:直接…...
C++_单列模式介绍
介绍 (1)…什么是单例 1.只能有一个实例化的对象的类(2).单例有什么用 1.多线程的线程池的设计 2.系统中只需要一个窗口时才使用单例(无法重复创建) 3.一个操作系统只能有一个文件系统(3).单例怎么用 1.隐藏所有构造函数 2.静态成员内部调用构造函数实例化 3.提供一个静态函数来…...
油烟净化器如何做到高效净化?科技力量,清新餐饮生活
我最近分析了餐饮市场的油烟净化器等产品报告,解决了餐饮业厨房油腻的难题,更加方便了在餐饮业和商业场所有需求的小伙伴们。 油烟净化器的出现,为我们的餐饮生活注入了一抹清新的色彩。然而,它究竟是如何工作的?为何能…...
【HTML5】HTML5 语音合成
一、前言 前一段时间在项目中需要用到播报文字语音。找到了 HTML 5 有这样的功能。 现在有时间进行总结下。 二、SpeechSynthesis SpeechSynthesis 接口是语音服务的控制接口。它可以用于获取设备上关于可用的合成声音的信息, 开始、暂停语音,或者别…...
顺序表的实现
目录 一. 数据结构相关概念 二、线性表 三、顺序表概念及结构 3.1顺序表一般可以分为: 3.2 接口实现: 四、基本操作实现 4.1顺序表初始化 4.2检查空间,如果满了,进行增容编辑 4.3顺序表打印 4.4顺序表销毁 4.5顺…...
深度学习中的池化
1 深度学习池化概述 1.1 什么是池化 池化层是卷积神经网络中常用的一个组件,池化层经常用在卷积层后边,通过池化来降低卷积层输出的特征向量,避免出现过拟合的情况。池化的基本思想就是对不同位置的特征进行聚合统计。池化层主要是模仿人的…...
Java面试整理-Java设计模式
Java中的设计模式通常是从更广泛的面向对象设计模式中借鉴而来的,这些模式旨在解决特定的设计问题和改善代码的可维护性、灵活性和可扩展性。设计模式大致可以分为三类:创建型、结构型和行为型。以下是这三类中一些常见的设计模式: 创建型模式 单例模式(Singleton):确保一…...
用CHAT了解更多知识点
问CHAT:什么是硅基生命和碳基生命? CHAT回复:硅基生命和碳基生命是两种理论性的生物体类型,这些生物体主要是由硅或碳元素以及其他元素构成的。 碳基生命是我们当前所熟知的生命形式。碳元素能够形成稳定且复杂的分子,…...
一个利用摸鱼时间背单词的软件
大家好,我是 Java陈序员。 最近进入了考试季,各种考试,英语四六级、考研、期末考等。不知道大家的英语四六级成绩怎么样呢? 记得大学时,英语四级都是靠高中学习积累的老本才勉强过关。 而六级则是考了多次ÿ…...
Matlab/Simulink的一些功能用法笔记(3)
01--引言 最近加入到一个项目组,有一些测试需要去支持,通过了解原先团队的测试方法后,自己作了如下改善,大大提高了工作效率。这也许就是软件开发的意义吧,能够去除一些重复的机械的人工操作并且结果还非常不可靠。 …...
Wafer晶圆封装工艺介绍
芯片封装的目的(The purpose of chip packaging): 芯片上的IC管芯被切割以进行管芯间连接,通过引线键合连接外部引脚,然后进行成型,以保护电子封装器件免受环境污染(水分、温度、污染物等)&…...
Mac OS 13+,Apple Silicon,删除OBS虚拟摄像头(virtual camera),
原文链接: https://www.reddit.com/r/MacOS/comments/142cv OBS为了捕获摄像头视频,将虚拟摄像头插件内置为系统插件了.如下 直接删除没有权限的,要删除他,在mac os 13以后,需要关闭先关闭苹果系统的完整性保护(SIP) Apple 芯片(M1,....)的恢复模式分为两种,回退恢复模式,和…...
精解 ES6 Promise 用法
🐱 个人主页:SHOW科技,公众号:SHOW科技 🙋♂️ 作者简介:2020参加工作,专注于前端各领域技术,共同学习共同进步,一起加油呀! 💫优质专栏&#x…...
Linux之基础I/O
目录 一、C语言中的文件操作 二、系统文件操作I/O 三、文件描述符fd 1、文件描述符的引入 2、对fd的理解 3、文件描述符的分配规则 四、重定向 1、重定向的原理 2、重定向的系统调用dup2 五、Linux下一切皆文件 一、C语言中的文件操作 1、打开和关闭 在C语言的文…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
