数据结构(邓俊辉)学习笔记】串 05——KMP算法:理解next[]表

文章目录

  • 1.快速移动
  • 2.避免回溯
  • 3.通配哨兵

1.快速移动

在接下来这节,就让我们从严格的意义上来理解 next 表的具体含义及其原理。
在这里插入图片描述

我们已经切实地看到, KMP 算法的优化效果首先体现在它可以使模式串得以快速地后移,而不是如蛮力算法那样只能亦步亦趋。反过来我们也可以认为 KMP 可以聪明地排除掉很多不必要的对齐位置。 而这些位置之所以被排除掉,是因为 KMP 发现它们不具备某种必要条件,正如我们马上就要看到的,这种必要条件就具体体现为模式串自身的某种匹配性。

依然回到这样一个串匹配的典型场景。我们在 T[i] 与 P[j] 之间发现了一次失配,接下来 KMP 会去查询 next 表,取出对应的表项 t,并用 P[t] 来取代此前的 P[j],使之继续以此前的 T[i] 相对齐,并从这个位置出发,继续后续的比对。

我们的问题是, KMP 在这种场合为何会选定这样一个特定的 t 呢?或者说,这样的 t 又具备哪些必要条件呢?答案就藏在上图中。

  1. 我们来考察 t 所对应的这个前缀( P[0,t) ),在KMP算法中,这个前缀将不再会重复地接受比对。我们已经看到,之所以能够这样,是因为 KMP 已经预先判定,这个前缀必然会与主串中对应的这个子串( P[ j - t, j) ) 完全匹配。在这里,我们需要回过头来考察,此前 P[j] 所对应的这个前缀,同样地,这个前缀在当年也应该和这个子串(i 所对应的行)是完全匹配的,因此,相对于它,文本串中这个长度为 t 的子串( P[ j - t, j) ) 就是一个后缀。
  2. 另一方面,既然这个新的前缀( P[0,t) ) 是由此前的前缀(j 所对应的行)经过右移之后而得到的,所以同样相对于此前的这个前缀,它依然是一个长度为 t 的前缀。

由此,我们也就得出了关于 t 的一个至关重要的必要条件:也就是说,在此前的这个前缀中,必须有一个长度为 t 的前缀与长度为 t 的后缀彼此相等。也就是说在相对于 P[j] 而言的这个前缀中,其首部和尾部必须具有一定的相似性。 这个必要条件,可以形式化地表示为上图中的等式。其左侧是一个真前缀,而右侧则是一个真后缀。

就任何一个特定的模式串 P 而言,对于区间内的任何一个整数 j,如果将满足上述条件的 t 筛选出来,就可以得到这样一个候选集合。

根据刚才的分析,既然这些 t 都满足上述必要条件,那么一旦在 T[i] 和 P[j] 处发生一次失配,只有来自于这个集合中的 t, 才有资格作为下一轮的对齐位置。

2.避免回溯

当然,你应该记得在这种情况下,KMP 并不会去逐一尝试所有的 t。事实上,在 next 表中,针对于每一项只会给出唯一的一种选择。那么 KMP 所选取的,究竟是其中的哪一个呢?

为此,我们需要考察这里的位移量( j - t)。是的,如果是用 t 来取代原来的 j,那么对应的位移量就应该是 j 和 t 之差。在这里 j 是相对固定的,因此 t 越小,对应的位移就越大。反之,t 越大,相应的位移也就越小。而位移量更小,也就意味着某种意义上的更加安全。什么意义呢?避免回溯。

是的,KMP 在所有候选者中最终所选取的的确就是这个集合中最大的那个 t。如此可以保证对应的位移量是安全的。实际上,这种原则也暗藏了另一个不变性,也就是说,由 KMP 所舍弃的那些对齐位置,的确都是不值得对齐的。

3.通配哨兵

至此,严谨的你或许会有一个疑问,这里的候选者集合 N(P, j) 一定是非空的吗?因为对于空集而言,无论是选取最大元,还是选取任何一个元素,都是无从谈起的。然而实际上,这种担心是不必要的。在这里,我们注意到只要 j 是正数,那么这个集合就必然包含0。

然而遗憾的是,j 可能恰好就是 0。当然,此时 P[ j ] 所对应的前缀 P[0 ,j) 也自然是空串。而我们知道对于空串而言,所谓的真前缀和真后缀都是不可能存在的,也就是说,此时的候选集合的确是一个空集。
在这里插入图片描述

为了修补这一漏洞,KMP算法所给出的建议是,统一将 next 表中的第0项视为-1。那么如何来理解这个-1呢?
在这里插入图片描述

一种形象而有效的理解方式就是,为每一个模式串在首字符的前端,也就是等效于秩为 -1 的位置增设一个哨兵。当然,与所有假想的哨兵一样,这个哨兵并不需要真实的存在,但是在逻辑上,这个哨兵却等效于一个与所有字符都通配的字符。

你应该还记得,我们在介绍 KMP 主算法时所搁置起来的一个问题。也就是其中那个 if 语句所对应的条件式,你应该记得,除了常规的字符比对逻辑,KMP 还增设了另一个并列的逻辑,也就是 j 是否小于0。现在你应该恍然大悟了吧?

是的,在正常的情况下,所谓的 j < 0 无非就是一种情况。也就说,在刚刚过去的那一轮比对中,我们失败于首次符 P[0]。于是,按照我们刚才所建议的那种理解方式,KMP 将用这个假想的通配符,去与文本串中适配的那个 T[i] 继续比对。既然是通配符,所以接下来的第一次比对必然会成功。也正因为此,我们可以将 j < 0 的条件,在语义上与字符的成功比对等效起来。也就是说,这个合成的逻辑判断式,在语义上完全等效于一次成功的比对。

由此可见,巧妙地引入和设置哨兵,在程序和算法设计过程中是一种非常高明的处理手法,KMP 就是这方面的一个典型范例。概括而言,这种手法的高明之处主要体现在两个方面。

  1. 首先,在代码实现上可以使得算法的描述更为简洁。
  2. 其次,通过相应的建立一种假想的模型,反过来,也可以使得我们对算法的理解更为统一和深入。

我们知道,包括伽利略在内的许多著名物理学家,都擅长于在头脑中进行所谓的虚拟实验。而实际上,计算机科学中的这种假想模式与物理学中的虚拟实验有着异曲同工之妙。

至此,我们已经对 KMP 所使用的那个 next 查询表有了足够深刻的认识。那么接下来一个问题自然就是,从计算的角度来看,这样一份查询表又当如何构造出来呢?为此,我们又需要花费多少成本呢?

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

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

相关文章

【STM32单片机_(HAL库)】3-4-4【中断EXTI】【智能排队控制系统】项目实现

3-4-2系统框图及硬件接线 3-4-3系统代码框架搭建 4.软件—tasks.c文件编写 排队控制系统状态机 tasks.c #include "tasks.h" #include "led.h" #include "beep.h" #include "exti.h" #include "lcd1602.h" #include &…

22. K8S及DevOps

22. K8S及DevOps 一. 章节简介二. DevOps1. 简介2. CICD三. Kubernetes[1. 官网](https://kubernetes.io/zh-cn/)--------------------------------------------------------------------------------------------------------一. 章节简介 二. DevOps 1. 简介 2. CICD

【C语言】文件操作 (详细!!)

1、为什么使用文件 使用文件的原因&#xff1a;使用文件主要是为了在程序的执行过程中保存、读取和交换数据。文件提供了一种持久化存储数据的方式&#xff0c;使得程序在关闭后&#xff0c;数据不会丢失&#xff0c;可以被其他程序或后续的程序执行周期重新读取和处理。 1.0 什…

Spring Boot启用GZIP压缩

1.为什么是需要gzip压缩&#xff1f; 经常我们都会与服务端进行大数据量的文本传输&#xff0c;例如 JSON 就是常见的一种格式。通过 REST API 接口进行 GET 和 POST 请求&#xff0c;可能会有大量的文本格式数据提交、返回。然后对于文本&#xff0c;它有很高的压缩率&#x…

神经网络——最大池化

1.Pooling Layers讲解&#xff1a; 最大池化有时也被称为下采样&#xff0c;对应的有上采样。注意ceil_mode参数的使用 2.代码实战&#xff1a; import torch from torch import nn from torch.nn import MaxPool2dinputtorch.tensor([[1,2,0,3,1],[0,1,2,3,1],[1,2,1,0,0],…

react 的学习随记

npx create-react-app my-app 创建一个名叫my-app的react的项目 npm run eject 运行 显示config 文件夹 react jsx &#xff08;使用时将babel 将jsx转为js&#xff09; 单页面时需要引用 1&#xff0c;样式&#xff08;在虚拟dom时&#xff09; 1. 引用样式时 用classNa…

ESP8266通过WiFiManager实现Web配网

背景 一个项目中使用到了一款压力传感器,需要通过单片机实现数据的采集并发送到远程的服务器上,单片机采用的时ESP8266,通过WiFiManager实现局域网配置,以及远端服务器IP地址和服务端口的配置。发布此文章记录一下使用WiFiManager实现配网的方法。 程序流程图 示例代码 …

NLP发展脉络-->特征优化阶段

NLP特征优化阶段 文本预处理特征提取降维与特征选择特征组合与扩展特征选择与评估特征工程的优化模型可解释性偏统计和规则的特征化阶段优缺点优点缺点 这是NLP的一个发展阶段。今天&#xff0c;我们就来了解一下NLP的特征优化阶段。特征优化在NLP的发展中曾经是一个至关重要的…

day-40 合并区间

思路 将二维数组按照第一列升序排列&#xff0c;把intervals[0][0]作为第一个区间的起点&#xff0c;将 intervals[0][1]和intervals[1][0]进行比较&#xff0c;如果intervals[0][1]<intervals[1][0]&#xff0c;则不能合并&#xff0c;否则可以合并&#xff0c;将Math.max(…

基于OpenCV+MFC的KCF测速软件

基于OpenCVMFC的KCF测速软件 引言原理介绍使用介绍&#xff08;1&#xff09;主界面&#xff08;2&#xff09;打开视频&#xff08;3&#xff09;点击KCF测速&#xff08;4&#xff09;框选待检测目标&#xff08;5&#xff09;测速结果 资源链接&#xff08;包含源码&#xf…

QT WIN11 FluentUI APP开发

代码 import QtQuick import QtQuick.Controls import FluentUIItem {property bool autoPlay: trueproperty int loopTime: 2000property var modelproperty Component delegateproperty bool showIndicator: trueproperty int indicatorGravity : Qt.AlignBottom | Qt.Align…

Gazebo Harmonic gz-harmonic 和 ROS2 Jazzy 注意事项

激光显示 点呈现 射线呈现 rviz2 新旧版本并存的混乱 本教程旨在为在Ubuntu Jammy&#xff08;最新支持Gazebo Classic包的Ubuntu版本&#xff09;上运行Gazebo Classic&#xff08;如Gazebo 11&#xff09;的用户提供指导&#xff0c;这些用户计划将其代码迁移到新的Gazebo版…

两个实用的Python编程技巧

一、变量类型声明技巧 虽然在Python中可以不用声明变量的类型&#xff0c;但是为了加快程序的运算速度&#xff0c;减少不必要的bug&#xff0c;我们可以在定义变量之初就把它的类型确定&#xff0c;这样可以更好地传输变量值。如下面的例子。 我们定义了两个变量&#xff0c…

基于STM32开发的智能家居语音控制系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 系统初始化语音识别处理设备控制与状态显示Wi-Fi通信与远程控制应用场景 家庭环境的语音控制办公室的智能化管理常见问题及解决方案 常见问题解决方案结论 1. 引言 随着人工智能技术的发展&…

Centos 添加双网卡 (生产环境配置记录)

1、在虚拟机中添加网卡2 [rootntpserver network-scripts]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo …

医疗器械法规笔记

目录 前言医疗器械法规体系医疗器械监管注册与备案前言 之前的文章中介绍了与软件开发过程中相关的法规(网络安全),同时介绍了如何查找相关行业标准,这些都是平时工作中遇到的细节问题,没有系统性的呈现出医疗器械法规相关的框架,一直想对法规与标准有一个全面的认识和总…

Redis中的 大/热 key问题 ,如何解决(面试版)

big key 什么是 big key? big key&#xff1a;就是指一个内存空间占用比较大的键(Key) 造成的问题&#xff1a; 内存分布不均。在集群模式下&#xff0c;不同 slot分配到不同实例中&#xff0c;如果大 key 都映射到一个实例&#xff0c;则分布不均&#xff0c;查询效率也…

常见错误导引 不锈钢螺钉的正确选购和使用分析

紧固件或螺钉是用于固定物体的机械工具。它们用于各种场景&#xff0c;从建造房屋、用具、玩具等。紧固件由多种材料制成&#xff0c;所有这些材料都有特定用途紧固件和用途。一些用于制造螺丝的材料包括不锈钢、铁、铜、铝和塑料。它通常会进行某种表面处理以提高其防锈性和/或…

(亲测解决)Couldn‘t open file /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9

1、报错 Extra Packages for Enterprise Linux 9 - x86_64 0.0 B/s | 0 B 00:00 Curl error (37): Couldnt read a file:// file for file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9 [Couldnt open…

K8S持久化存储数据volumeMountsvolumes

环境&#xff1a; Ubuntu-1:192.168.114.110作为主 Ubuntu-2:192.168.114.120作为从1&#xff0c;node节点1 Ubuntu-3:192.168.114.130作为从2&#xff0c;node节点2 持久化volumeMounts pod里面&#xff1a;emptyDir和hostPath。存储在node&#xff0c;NFS...&#xff0c;Clo…