KMP算法的实现

news2024/9/21 8:32:28

         这是C++算法基础-数据结构专栏的第二十六篇文章,专栏详情请见此处


引入

        KMP算法是一种可以快速查找某一字符串在一个文本中的所有出现的算法。

        下面我们就来讲KMP算法的实现。

定义

        Knuth–Morris–Pratt 算法,简称KMP算法,是由Knuth、Pratt和Morris在1977年共同发布的一个算法,它是前缀函数的一个典型应用,应用是找到并展示一个字符串在中一个文本的所有出现。

过程

        前缀函数

        什么是前缀函数?要想了解这个函数,我们需要了解一下一个字符串的前缀,真前缀,后缀和真后缀这四个概念。

        前缀是指从串首开始到某个位置结束的一个特殊子串,而真前缀就是指除了这个字符串本身以外的前缀;后缀是指从某个位置开始到串尾结束的一个特殊子串,而真后缀就是指除了这个字符串本身以外的后缀。

        了解了以上的概念,我们再来看前缀函数的定义

        给定一个长度为n的字符串s,它的前缀函数被定义为一个长度为n的数组ne[]。其中ne[i]表示了子串s[1\cdots i]拥有的最长的一对相等的真前缀(s[1\cdots k])与真后缀(s[i-k\cdots i])的长度k(若没有,即为0)。

        KMP算法就是前缀函数的经典应用。接下来,我会展示一道KMP算法所实现的一道经典问题,从而讲解算法的思路。

        例题

        题目大意:给定一个文本和一个文本,找到并展示这个字符串在这个文本的所有出现时的下标。

        刚看到题面,可能大家只会打暴力,思路就是:从头开始比对字符串。若比对成功,则展示下标;若在比对时出现不同的字符,则停止比对,再从下一个位置继续比对。重复以上操作,直到遍历完成。

        聪明的小伙伴可能看出,比对的过程不能再优化了,进行优化的只能是比对失败后对于字符串的下一个比对位置,换句话说,比对失败后,我们不再从下一个位置继续比对,而是可以往后移动几位再比对,从而减少不必要的操作。

        而这个思路,就是KMP算法的核心思路。

        KMP算法主体

        对于正在比对的字符串str,它是在文本下标为i的位置开始比对的,并在文本下标为j的位置出现不同的字符,比对失败的。假设文本[i\cdots j-1]拥有一对相等的真前缀(s1)与真后缀(s2),又因为文本的真前缀有相对应的字符串的部分(s3),所以s1=s2=s3。又因为s2=s3,所以s3的是可以在s2的位置进行下一次比对的。这就是KMP算法的实现原理。

        很明显,上述操作实际上就是应用了前缀函数,为了方便快捷,我们可以先求出字符串(在上一段,我说的是文本的一对相等的真前缀与真后缀,其实文本[i\cdots j-1]是有字符串对应的)的前缀数组,再进行以上操作。

        还有最后一个要点,前缀函数求的是字符串拥有的最长的一对相等的真前缀与真后缀的长度,实际上,看似是最长,实际上最长的真后缀的起始位置最往前,但这样就避免了中间有遗漏的比对位置。

        在核心代码中,我使用了双指针算法,若文本长度为n,字符串长度为m,则时间复杂度为O(n+m)。如果想了解双指针算法的具体内容,可以移步至我的这篇博客:双指针算法的实现。

        一句话送给大家:

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

——KMP        

        嗯,这句话不是我说的,是我在网上看到的,但是它很好地概括了KMP算法的核心,也很有哲理。

性质

        时间复杂度

        O(n+m),在KMP算法主体中已经分析,故不再讲解。

代码

        下面给出KMP算法的实现代码:

string s,p;
int n,m;

for(int i=2,j=0;i<=m;i++){
    while(j&&p[i]!=p[j+1])
		j=ne[j];
    if(p[i]==p[j+1])
		j++;
    ne[i]=j;
}

for(int i=1,j=0;i<=n;i++){
    while(j&&s[i]!=p[j+1])
		j=ne[j];
    if(s[i]==p[j+1])
		j++;
    if(j==m){
        j=ne[j];
        
    }
}
        代码解释

        第一行的sp分别代表文本和字符串,第二行的nm分别代表sp的长度,第一个for循环是前缀函数的实现,第二个for循环是KMP算法主体的实现


上一篇-单调队列的实现    C++算法基础专栏文章    下一篇-​​​​​​​Trie树之字符串统计问题


每周六更新一篇文章,内容一般是自己总结的经验或是在其他网站上整理的优质内容

点个赞,关注一下呗~

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

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

相关文章

2024华为杯数学建模竞赛E题

2024年中国研究生数学建模竞赛E题 高速公路应急车道紧急启用模型 高速公路拥堵现象的原因众多&#xff0c;除了交通事故外&#xff0c;最典型的就是部分路段出现瓶颈现象&#xff0c;主要原因是车辆汇聚&#xff0c;而拥堵后又容易蔓延。高速公路一些特定的路段容易形成堵点&…

云手机的便捷性和安全性体现在哪?

随着5G技术的迅速发展&#xff0c;云手机在游戏、电商以及新媒体营销等领域中的应用日益广泛。它不仅能够显著降低成本、提升效率&#xff0c;还随着边缘计算和云技术的进步&#xff0c;展现出无限的增长潜力。 云手机的便捷性体现在哪里&#xff1f; 云手机的便捷性毋庸置疑。…

煤矿智慧矿井数据集 (1.煤矿采掘工作面智能分析数据集2.煤矿井下钻场智能分析数据集 )

智慧矿井智能分析数据集 数据1&#xff1a;数据1包含煤矿采掘工作面工人安全帽检测&#xff0c;工人行为检测&#xff08;行走&#xff0c;站立&#xff0c;坐&#xff0c;操作&#xff0c;弯腰&#xff0c;靠&#xff0c;摔&#xff0c;爬&#xff09;&#xff0c;液压支撑防护…

C++ | Leetcode C++题解之第421题数组中两个数的最大异或值

题目&#xff1a; 题解&#xff1a; struct Trie {// 左子树指向表示 0 的子节点Trie* left nullptr;// 右子树指向表示 1 的子节点Trie* right nullptr;Trie() {} };class Solution { private:// 字典树的根节点Trie* root new Trie();// 最高位的二进制位编号为 30static…

en造数据结构与算法C# 用Unity实现简单的群组行为算法 之 对齐

en造数据结构与算法C# 用Unity实现简单的群组行为算法 之 聚集-CSDN博客 en造数据结构与算法C# 用Unity实现简单的群组行为算法 之 聚集-CSDN博客 演示 思路 1.检测 自然是沿用前两节的检测范围 2.对齐朝向 对齐朝向就是邻居鸟的forward加起来再除总数得到平均数 3.对齐…

企业急于采用人工智能,忽视了安全强化

对主要云提供商基础设施上托管的资产的安全分析显示&#xff0c;许多公司为了急于构建和部署 AI 应用程序而打开安全漏洞。常见的发现包括对 AI 相关服务使用默认且可能不安全的设置、部署易受攻击的 AI 软件包以及不遵循安全强化指南。 这项分析由 Orca Security 的研究人员进…

关于机器学习和深度学习的区别有哪些?

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于机器学习和深度学习区别的相关内容&…

Altium Designer(AD)百度云下载与安装(附安装步骤)

在我们日常使用当中&#xff0c;Altium designer常常也被简称为AD&#xff0c;是一款一体化的电子产品开发系统软件&#xff0c;主要运行在Windows操作系统上。 我们通过Altium designer把原理图设计、电路仿真、PCB绘制编辑、拓扑逻辑自动布线、信号完整性分析和设计输出等技…

企业为什么要做算法备案?

企业为什么要做算法备案&#xff1f; 在数字经济迅速发展的今天&#xff0c;算法已成为推动各行各业创新发展的核心动力。鉴于此&#xff0c;国家层面正积极构建完善的监管框架&#xff0c;旨在促进算法应用的健康发展&#xff0c;确保其在法治轨道上运行。 近期&#xff0c;一…

揭开数据能力的神秘面纱

在当今数字化时代&#xff0c;数据已成为企业和组织的重要资产。拥有强大的数据能力&#xff0c;能够帮助企业更好地理解市场、客户和业务&#xff0c;从而做出更明智的决策。然而&#xff0c;数据能力究竟是什么&#xff1f;它包含哪些方面&#xff1f;又如何提升呢&#xff1…

银河麒麟桌面操作系统V10(SP1)ssh服务安装与配置

在国产化的大背景下,各种国产操作系统逐步进入运维人员的视野,ssh作为linux远程连接工具,是运维人员必需的工具之一。本文主要介绍在银河麒麟桌面操作系统V10(SP1)上安装和配置ssh服务。 准备工作 1、查看操作系统信息 cat /etc/os-release 笔者操作系统为银河麒麟桌面操…

一款能够管控企业计算机的安全系统 | 企业终端安全管控 | 天锐DLP数据安全

天 锐 DLP可帮助企业规范对电脑计算机的使用管理&#xff0c;对USB存储设备、终端外节设备、桌面壁纸进行统一管控&#xff0c;支持限制控制面板、计算机管理、系统下的相关功能选项的使用。 【地址&#xff1a;点击了解天锐股份数据安全产品】 1.计算机设置 天锐DLP可对计算…

uniapp|微信小程序 实现输入四位数 空格隔开

<template><page-meta :page-style"cssVar"></page-meta><view class"container"><u-navbartitle"优惠券兑换"placeholderbgColor"#fff":autoBack"true":titleStyle"{fontFamily: SourceHa…

VScode 修改 cursor 键盘设置

vscode 中按下 ctrl K 后 ctrl s 打开键盘快捷键设置。 搜索光标 cursor 找到 cursorDown 以及对应需要修改的快捷键命令 右键 添加快捷键设置 修改即可 alt space 关闭win设置中的中英文切换 代码提示下移 selectPrevSuggestion 上移

模拟自然的本质:与IBM量子计算研究的问答

量子计算可能是计算领域的下一个重大突破&#xff0c;但它的一般概念仍然处于炒作和猜测的现状&#xff1f;它能破解所有已知的加密算法吗&#xff1f;它能设计出治愈所有疾病的新分子吗&#xff1f;它能很好地模拟过去和未来&#xff0c;以至于尼克奥弗曼能和他死去的儿子说话…

windows环境下MySQL启动失败 查看data文件夹中.err发现报错unknown variable ‘log‐bin=mysql‐bin‘

文章目录 问题解决方法 问题 今天在windows环境下配置MySQL主从同步&#xff0c;在修改my.ini文件后发现MySQL启动失败了 打开my.ini检查参数发现没有问题 [mysqld] #开启二进制日志&#xff0c;记录了所有更改数据库数据的SQL语句 log‐bin mysql‐bin #设置服务id&#x…

网络高级day01(Modbus 通信协议:Modbus TCP)

目录 1》modbus分类 1> Modbus RTU 2> Modbus ASCLL 3> Modbus TCP 2》Modbus TCP的特点 3》Modbus TCP协议 1> 报文头&#xff08;一共7个字节&#xff09; 2> 寄存器 3> 功能码 4> 数据 01H 功能码分析 05H 功能码分析 0FH 功能码分析 1》modbus…

Springboot常见问题(bean找不到)

如图错误显示userMapper bean没有找到。 解决方案&#xff1a; mapper包位置有问题&#xff1a;因为SpringBoot默认的包扫描机制会扫描启动类所在的包同级文件和子包下的文件。注解问题&#xff1a; 比如没有加mapper注解 然而无论是UserMapper所在的包位置还是Mapper注解都是…

虚拟机ens33网卡不显示inet地址(已设置NOBOOT为yes)

在虚拟机中输入ifconfig或ip addr时&#xff0c;出现如下情况&#xff1a; sudo dhclient ens33sudo ifconfig ens33依次执行上面两行&#xff0c;之后发现ens33中可以显示inet了 本虚拟机的地址就是192.168.244.131

Unity屏幕震动效果

基于Cinemachine 1、为Cinemachine设置拓展 2、选择ImpulseListener 3、为摄像机跟随的角色添加脚本 4、设置Impulse 5、选择类型 6、设置内置6DShake并调节振幅 7、运行时invoke即可