数据结构(邓俊辉)学习笔记】串 03——KMP算法:记忆法

news2025/1/11 23:44:55

文章目录

  • 1. 重复匹配的前缀
  • 2. 不变性
  • 3. 记忆力
  • 4. 预知力

1. 重复匹配的前缀

在这里插入图片描述

关于串匹配,包括蛮力算法在内,至少有30多种知名的算法,而接下来,就将介绍其中最为经典的 KMP 算法。这个算法之所以著名,不仅是由于它出自包括 Knuth 在内的若干名人之手,而更重要的是,它正如我们此前所期盼的那样,能够保证即便在最坏的情况下,运行时间也不超过线性O(n)。

当然,在这一部分的末尾,我们也将通过对比指出,这一算法从某种意义上讲,也是被过度地神化了。

正所谓不破不立,我们的 KMP 之旅,是起始于蛮力算法。首先来揭示,蛮力算法为什么会如此低效。
在这里插入图片描述

从宏观上来看,蛮力算法的一次典型运行过程,可以由这样一幅图来示意。假定这就是足够长的一个文本串,而下面则是相对而言更短的模式串。我们知道,在算法的每一步迭代中,相对于文本串,模式串都有一个相应的对齐位置。

请注意,在这个算法中,相邻的对齐位置之间,间隔都是一个字符。在每一对齐位置,这个算法都需要从首字符开始,进行一系列的比对,直至在某个位置发生失配。请注意,在此之前每一次迭代所花费的时间都正比于这样一个前缀。

在这个图中,我们可以清晰地看到,所有这些前缀之间存在着大量的重复。也就是说在此前曾经参与比对的字符,在后续的迭代中,往往还会再次地参与比对。如果我们将视线集中于文本串中的某一特定字符,就会发现,在最坏情况下,它有可能会与模式串中的每一个字符都比较一次。也就是说,文本串中的每一个字符,都有可能参与多达 M 次的比对。

依然回到我们上一节末尾,针对蛮力算法所给的那个最坏实例。我们可以从这样一个新的角度来阐释,为什么蛮力算法效率如此低下。因为站在文本串中每一个字符的角度来看,在这种最坏情况下,它都会与模式串中的每一个字符比对一次。

在这类这坏情况下,每一步迭代都需要经过长途跋涉,才能够在最后一个位置发现失配。因此,反过来,这类情况之所以棘手,也可以理解为在模式串中存在大量与文本串能够局部匹配的前缀,而蛮力算法的计算成本,也主要消耗于这些前缀中。

然而,在对这个具体的实例进一步观察之后,我们或许会发现,这些局部匹配前缀所涉及的比对,绝大多数都是不必进行的,至少不必反复进行。能看出其中的原因吗?

2. 不变性

在这里插入图片描述
应该记得,我们在分析蛮力算法时,曾经指出过这个算法的一个不变性。没错,不变性。整个算法过程中的任何一个时刻,都可以表示为这样一幅具有一般意义的插图。是的,在当前假设我们需要对 T[i] 和 P[j] 进行比对,并且根据比对的结果,来确定算法的下一步走向。

而这里所蕴含的不变性就是,这个子串与这个前缀完全相等。是的,子串与前缀完全相等。这意味着什么呢?是的,这意味着我们已经完全掌握了这个子串的全部信息。也就说它具体是由哪些字符所构成的,而这类信息完全可以为后续的各步比对所利用。

还是回到我们刚才的那个例子,考察在当前这步迭代中的最后一次比对,也就是那次失败的比对,正如我们的不变性所指出的,尽管这次比对是失败的,但它却意味着在此前我们已经获得过足够多次成功的比对。就这个例子而言,也就是一系列的0-0匹配。没错,0-0匹配。

这一点其实可以概括为一条非常有用的信息。具体来说也就是,在主串中对应的这个子串完全是由0构成的。没错,在这种情况下,与模式串前缀所对应的文本串的子串完全是由0构成的。

很可惜,此前的蛮力算法没有注意到并且充分利用这一点。事实上,它会正规中矩地将模式串右移一个字符,然后试图重新与这个子串进行匹配。现在应该不难理解,实际上,既然无论是这个字串还是这个前缀,都是完全由0所构成的,所以它们的任何局部比对都必然会整体成功。

这意味着,至少在当前的这种情况下,这个子串与这个模式串的任何比对,都会以完全匹配而返回。尽管它们的第一次比对的确有必要,但如果像蛮力算法那样,在此后还反复地将它们进行比对,就显然是没有必要的。

3. 记忆力

在这里插入图片描述

事实上,只要我们记忆力足够强,自然也就可以将在前一轮比对中所获得的上述信息存储起来,并为后续的比对所利用。

而这类信息的使用原理与方法则可以由上图来表示。请再次确认这个图所对应的场景:也就是在当前的对齐位置,我们首次在 T[i] 和 P[j] 处发生了一次失配。而反过来,P[j]所对应的那个前缀以及 T[i] 所对应的那个子串是完全匹配的。

只要我们能够充分地利用这类信息,就可以迅速地排除掉大量的对齐位置,从而令模式串得以迅速地、大幅度地向后滑动。

而且同样是利用这类信息,我们甚至可以不必去重复比对在 T[i] 之前的任何字符。也就是说在模式串的下一对齐位置,新一轮的比对只需从 T[i]与新的 P[j]开始。

4. 预知力

在这里插入图片描述
依然回到我们已经多次使用的这个二进制串的实例,根据刚才的分析,在当前这轮比对失败于模式串的末字符之后,即便我们依然只能向后移动一个字符,但相对于新的 P[j] 而言,整个前缀都无需重复比对了。

也就是说,我们只需从上一次失败的位置出发,继续进行下一轮的比对。正所谓从哪里跌倒的就从哪里爬起来。实际上,即便是对于更为复杂的例子,也依然存在此类优化的可能。

比如这就是一例,其模式与刚才类似。也就是说,相对于当前这个对齐位置,我们所做的一轮比对首次失败于 e 和 o 之间的失配。请注意,在这种情况下,我们完全不必亦步亦趋的右移模式串,而是可以大胆地将它后移三个字符,也就是说此前的两个对齐位置都可以排除掉。

你能看出这背后的原因吗?没错。如果一个位置值得对齐。那么它的一个必要条件就是,所对应的首字符应该与模式串的首字符一样,也是 R。在这种情况下,无论E或G 都不是 R 。

这里我们再强调一次,关于这个子串的所有信息,都是我们通过前一轮的比对所获得的。而通过这两个实例,我们已经切实地看到,只要我们能够对这类信息充分加以利用,就可以获得两个方面的优化效果。

  1. 一方面,我们可能大幅度地向后滑动模式串;

  2. 而另一方面,我们也可避免大量重复的比对。

    而为了同时兑现这两个方面的优化,我们算法实际上只需具有某一种预知力即可。具体来说也就是,在每一次失败之后,我们应该将模式传中的哪一个字符与文本串中刚才失败的那个字符,彼此重新对齐,并继续从这个位置开始进行比对。在这个例子中也就是要确定这个0,而在这个例子中,相应的对齐位置也就是这个 E。

那么具体地,又当如何来确定此类继任字符的位置呢?为此我们需要花费多少时间和空间?而且更重要地,既然是作为预知力,我们的算法,能否在事先就提前确定此类继任字符的位置呢?好消息是,所有这些都是可能的。

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

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

相关文章

Autosar(Davinci) --- ADT和IDT如何Mapping

前言 这里我们讲一下ADT如何与IDT进行Mapping 一、ADT为什么要与IDT进行Mapping 二、ADT和IDT如何Mapping 鼠标右键【type Mapping Sets】,选择【New Data type Mapping Set...】 打开之后,我们起一个名字【DemoTypeMapping】 然后选择【Data Type Maps】来将ADT与IDT进行m…

SpringBoot+Grafana+Prometheus+Docker-Compose 快速部署与JVM监控的快速入门的简单案例

1. Java项目 1.1 项目结构 1.2 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"htt…

ThingsGateway:一款基于.NET8开源的跨平台高性能边缘采集网关

前言 今天大姚给大家分享一款基于.NET8开源的跨平台高性能边缘采集网关&#xff0c;提供底层PLC通讯库&#xff0c;通讯调试软件等&#xff0c;单机采集数据点位可达百万&#xff1a;ThingsGateway。 项目技术栈 后端技术栈&#xff1a;支持.NET 6/7/8&#xff0c;Sqlsugar&am…

爬虫使用优质代理:确保高效稳定的数据采集之道

爬虫使用优质代理的最佳实践 在进行网络爬虫时&#xff0c;使用优质代理就像是为你的爬虫装上了强劲的发动机&#xff0c;能够大幅提升数据抓取的效率和成功率。然而&#xff0c;选择和使用优质代理并非易事&#xff0c;今天我们就来探讨如何在爬虫中有效使用优质代理。 1. 什…

vue3组件封装系列-表格及分页-第二弹

第二弹来了&#xff0c;不知道有多少人是看过我的第一篇文章的&#xff0c;今天本来是没想更新的&#xff0c;但是现在项目正在验收期准备上线&#xff0c;闲着还不如来发发文。虽然这两天可能会高产&#xff0c;下一次高产就不知道是什么时候了。话不多说&#xff0c;先上图。…

OpenGuass under Ubuntu_22.04 install tutorial

今天开始短学期课程&#xff1a;数据库课程设计。今天9点左右在SL1108开课&#xff0c;听陈老师讲授了本次短学期课程的要求以及任务安排&#xff0c;随后讲解了国产数据库的三层架构的逻辑。配置了大半天才弄好&#xff0c;放一张成功的图片&#xff0c;下面开始记录成功的步骤…

数据融合的超速引擎——SeaTunnel

概览 SeaTunnel是一个由Apache软件基金会孵化的数据集成工具&#xff0c;专为应对大规模数据的快速处理而设计。它以高效的数据处理能力和简洁的架构&#xff0c;帮助企业在数据仓库构建、实时数据处理和数据迁移等场景下&#xff0c;实现数据流的无缝整合。SeaTunnel的设计理…

LDO工作原理与仿真

LDO工作原理与仿真 目录 LDO工作原理与仿真一、LDO内部电路组成1. 基准电压源&#xff08;Reference Voltage Source&#xff09;2. 误差放大器&#xff08;Error Amplifier&#xff09;3. 功率调整元件&#xff08;Power Adjustment Element&#xff09;4. 分压取样电路&#…

用于不平衡分类的 Bagging 和随机森林

用于不平衡分类的 Bagging 和随机森林 Bagging 是一种集成算法&#xff0c;它在训练数据集的不同子集上拟合多个模型&#xff0c;然后结合所有模型的预测。 [随机森林]是 bagging 的扩展&#xff0c;它也会随机选择每个数据样本中使用的特征子集。bagging 和随机森林都已被证…

【Word与WPS如何冻结首行首列及窗口】

1.Word如何冻结首行首列及窗口 microsoft word 中锁定表头是一项实用的功能&#xff0c;可让您在滚动文档时保持表头可见。这在处理大型文档或包含大量数据的表格时非常有用。php小编柚子将为您详细介绍 word 锁定表头位置的方法&#xff0c;帮助您轻松掌握这项实用技巧。 1.…

实体书商城小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;小说分类管理&#xff0c;小说信息管理&#xff0c;订单管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;小说信息&#xff0c;小说资讯&#xff0…

Qt_两种创建组件的方式-通过图形化-通过代码

文章目录 一、通过图形化的方式&#xff0c;在界面上创建一个控件&#xff0c;显示hello world1.打开UI设计界⾯2.拖拽控件⾄ ui 界⾯窗⼝并修改内容3.构建并运行 二、通过代码的方式&#xff0c;通过编写代码&#xff0c;在界面上创建控件&#xff0c;显示hello world在Widget…

手撕python之基本数据类型以及变量

​​​​​​1.基础概念 python就是将不同的数据划分成了不同的类型 就像我们生活中的数据有数字、字符等数据一样 小知识点&#xff1a; 注释&#xff1a;# 全体注释&#xff1a;AltF3 取消注释&#xff1a;AltF4 2.数值类型 数值类型概括 数值类型分为三种&#xff…

Cesium 展示——动态洪水淹没效果

文章目录 需求分析1. 引入插件2. 定义变量3. 开始绘制3.1 绘制点3.2 绘制线3.3 绘制面3.4 开始分析(第一种)3.5 开始分析(第二种)3.6 方法调用4. 整体代码其他需求 从低处到高处实现洪水淹没效果 分析 本篇文章对方法进行单独抽离,因此支持拿来即用,注意传参就可 1. …

宠物系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;商品信息管理&#xff0c;店主管理&#xff0c;猫狗查询管理&#xff0c;猫狗宠物社区&#xff0c;管理员管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&…

宝塔 出现 请使用正确的入口登录面板

目录 前言1. 问题所示2. 原理分析3. 解决方法 前言 记录实战中所有的问题导向、原理分析以及解决方法 1. 问题所示 在登录宝塔的时候&#xff0c;出现如下问题 请使用正确的入口登录面板 错误原因&#xff1a;当前新安装的已经开启了安全入口登录&#xff0c;新装机器都会随…

使用redis模拟cookie-session,例子:实现验证码功能

目录 在前后端分离架构中不建议使用cookie-session机制实现端状态识别 所以我们可以使用redis来模拟session-cookie机制 下面我们通过实现验证码的功能来举例 第一步&#xff1a;了解前端要我们返回的数据变量名字&#xff0c;变量类型 1.封装code,data成一个result类&…

多模态技术应用场景探析,景联文科技多模态数据测试平台推动多模态大模型技术突破

多模态技术应用场景探析&#xff0c;景联文科技多模态数据测试平台推动多模态大模型技术突破 在大语言模型背景下&#xff0c;多模态技术的发展已成为一个重要趋势。 Sora是OpenAI推出的多模态大模型&#xff0c;具备高级视频生成与编辑功能&#xff0c;支持长视频、多视角、多…

使用OpenCV库来捕获摄像头视频流,并按指定格式保存

今天我们来使用OpenCV库来捕获摄像头视频流&#xff0c;并将其保存为AVI格式的视频文件&#xff0c; 代码的主要功能包括&#xff1a; 初始化摄像头捕获对象。设置视频编解码器和输出文件路径。循环读取视频帧&#xff0c;处理并保存到文件中。显示处理后的视频帧。按下q键退…

Python | 处理海洋2C 数据 | 非标准时间格式

写在前面 最近&#xff0c;师弟在用Python读取某海洋2C数据时&#xff0c;突然冒出一个报错&#xff1a;“时间单位的参考日期无效&#xff0c;当前日期 00:00:00.0”。这让我回想起&#xff0c;似乎在很久很久以前&#xff0c;我处理SMAP和Argo数据时也遇到过类似的问题。为了…