数据结构: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就是第一个匹配项的下标了。

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

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

相关文章

【期刊周报1】医学好刊(SCI/SSCI/EI),含Top,领域广,接收快!

为了向广大学者朋友提供更优质的选刊服务&#xff0c;提高选刊质量&#xff0c;我处现开设周报专栏&#xff0c;以罗列我处合作的优质期刊~ 本期&#xff0c;小编给大家推荐的是医学领域相关的热门期刊&#xff0c;接收领域广&#xff0c;无预警&#xff0c;且在最新检索目录内…

Python遥感影像深度学习指南(2)-在 PyTorch 中创建自定义数据集和加载器

在上一篇 文章中,我们Fast.ai 在卫星图像中检测云轮廓,检测物体轮廓被称为语义分割。虽然我们用几行代码就能达到 96% 的准确率,但该模型无法考虑数据集中提供的所有输入通道(红、绿、蓝和近红外)。问题在于,深度学习框架(如 Keras、Fast.ai 甚至 PyTorch)中的大多数语…

redis哨兵+redis主从复制(在虚拟机centos的docker下)

1.安装docker Docker安装(CentOS)简单使用-CSDN博客 2.redis主从复制 redis主从复制(在虚拟机centos的docker下)-CSDN博客 3.编辑3个redis配置 cd /etc mkdir redis-sentinel cd redis-sentinel/ wget http://download.redis.io/redis-stable/sentinel.confcp sentinel.co…

【并发编程篇】读锁readLock()和写锁writeLock()

文章目录 &#x1f6f8;情景引入⭐解决问题 readLock()和writeLock()都是ReadWriteLock接口中定义的方法&#xff0c;用于获取读锁和写锁。 readLock()方法返回一个读锁&#xff0c;允许多个线程同时获取该锁&#xff0c;以进行并发读取操作。如果当前已有一个写锁或其他线程正…

GIT具体配置步骤详解

GIT配置具体步骤如下 SDK 使用 Repo 工具管理&#xff0c;拉取 SDK 需要配置安装 Repo 工具。 Repo is a tool built on top of Git. Repo helps manage many Git repositories, does the uploads to revision control systems, and automates parts of the development workf…

多维时序 | MATLAB实CNN-BiGRU-Mutilhead-Attention卷积网络结合双向门控循环单元网络融合多头注意力机制多变量时间序列预测

多维时序 | MATLAB实现CNN-BiGRU-Mutilhead-Attention卷积网络结合双向门控循环单元网络融合多头注意力机制多变量时间序列预测 目录 多维时序 | MATLAB实现CNN-BiGRU-Mutilhead-Attention卷积网络结合双向门控循环单元网络融合多头注意力机制多变量时间序列预测预测效果基本介…

ubuntu 22.04 安装mysql服务

完整内容&#xff1a; https://developer.aliyun.com/article/1260321 # 安装服务 sudo apt install mysql-server# 按向导设置root密码 sudo mysql_secure_installation# 使用设置的密码登录 sudo mysql -u root -p也可以使用工具登录&#xff0c;例如: navicat for mysql

协同工作php,PHPOA:灵活、高效、协同,让企业高效运转

原标题&#xff1a;PHPOA&#xff1a;灵活、高效、协同&#xff0c;让企业高效运转PHPOA系统作为一个管理系统&#xff0c;它的职责就是为企业高效运转而服务&#xff0c;以提高企业的办公效率为己任&#xff0c;减少不必要的资源浪费为责任。它保持高度的灵活性、高效性与协同…

ubuntu搭建php开发环境记录

2019独角兽企业重金招聘Python工程师标准>>> 这两天自己在阿里云上面买了一个ecs&#xff0c;系统选的是ubuntu16.04&#xff0c;第一件事就是先搭环境&#xff0c;这次准备使用lamp组合。 Apache安装 首先安装apache服务器&#xff0c;ubuntu下面使用apt-get来下载…

Web端H.265播放器研发解密

音视频编解码对于前端工程师是一个比较少涉足的领域&#xff0c;涉及到流媒体技术中的文本、图形、图像、音频和视频多种理论知识的学习&#xff0c;才能够应用到具体实践中&#xff0c;本团队在多媒体领域深耕两年多&#xff0c;才算是有一定产出&#xff0c;我们自研web播放器…

拳击 武术java父类,拳击是一种很有力量的武术类型

原标题&#xff1a;拳击是一种很有力量的武术类型拳击是一种很有力量的武术类型&#xff0c;拳击比赛策略有很多&#xff0c;围绳技术是其中之一。那么拳击比赛策略技巧有哪些呢&#xff1f;下面养生之道网为您解析拳击比赛策略技巧有哪些&#xff0c;看看吧。1、当拳手靠在围绳…

kaka 1.0.0 重磅发布,服务于后端的事件领域模型框架。

百度智能云 云生态狂欢季 热门云产品1折起>>> kaka 1.0.0正式发布了&#xff0c;从三个月前的kaka-notice-lib 1.0.0的发布&#xff0c;经过多次研磨&#xff0c;终于迎来了本次重大更新。 kaka是一款服务于java后端的事件领域模型框架&#xff0c;主要目的为解耦业…

如何把WAV格式音频转换为MP3格式

WAV为微软公司&#xff08;Microsoft)开发的一种声音文件格式&#xff0c;它符合RIFF(Resource Interchange File Format)文件规范&#xff0c;用于保存Windows平台的音频信息资源&#xff0c;被Windows平台及其应用程序所广泛支持&#xff0c;因此在声音文件质量和CD相差无几&…

恶意软件盯上了加密货币,两家以色列公司受到攻击

近日&#xff0c;网络安全公司Palo Alto Networks威胁研究部门Unit 42发博称&#xff0c;已确认Cardinal RAT自2017年4月起对两家从事外汇和加密交易软件开发的以色列金融科技公司发起过攻击。 Cardinal RAT是可远程访问特洛伊木马&#xff08;RAT&#xff09;&#xff0c;攻击…

php 自定义打印模板下载,PHP – 创建自定义模板系统?

我已经在这里搜索过,令人惊讶的是我找不到答案.我发现了一个类似的线程,但没有真正的解决方案.复杂的部分是循环,如果我不需要循环我可以只是做一个常规替换.所以,我有一个带有一些标记的.html文件,如下所示&#xff1a;{{startloop}}{{imgname}}{{endLoop}}我想要做的是用其他…

腾讯财报中“最大秘密”:2018云收入91亿元,交首份TO B答卷

腾讯财报中“最大秘密”云业务收入又一次被公开了&#xff1a;2018年&#xff0c;腾讯云收入91亿元&#xff0c;增长100%。 3月21日&#xff0c;腾讯发布2018年Q4及全年财报&#xff0c;2018全年收入3126.94亿元同比增长32%&#xff0c;净利润(Non-GAAP)774.69亿元。而被列进“…

根据坐标如何在matlab中l连成曲线,matlab中,如何将两条曲线画在一个坐标系里,plot(x1,x2,y1,y2)还是怎样...

matlab中&#xff0c;如何将两条曲线画在一个坐标系里&#xff0c;plot(x1,x2,y1,y2)还是怎样以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;matlab中&#xff0c;如何将两条曲线画在一个坐…

java已被弱化签名,高效Java第四十条建议:谨慎设计方法签名

作用有助于设计易于学习和使用的API。如何做——谨慎地选择方法的名称1.选择易于理解的&#xff0c;并且与同一个包中的其他名称风格一致的名称。2.选择与大众认可的名称相一致的名称。如何做——不要过于追求提供便利的方法每个方法都应该尽其所能。方法太多会使类难以学习、使…

phpexcel.php linux,phpexcel在linux系统报错如何解决

最近有个tp3.2的项目迁移到linux系统上了&#xff0c;突然有天发现原本在win server 2008上运行没问题的excel导出功能在新的系统上不能使用了。报错如下&#xff1a;说是1762行有问题&#xff0c;找到这个文件的代码看看&#xff1a;/*** Get an instance of this class** acc…

asp.net core系列 48 Identity 身份模型自定义

一.概述 ASP.NET Core Identity提供了一个框架&#xff0c;用于管理和存储在 ASP.NET Core 应用中的用户帐户。 Identity添加到项目时单个用户帐户选择作为身份验证机制。 默认情况下&#xff0c;Identity可以使用的 Entity Framework (EF) Core 数据模型。 本文介绍如何自定义…