扩展KMP

news/2024/10/24 21:58:55/文章来源:https://www.cnblogs.com/binbin200811/p/18501417

前言

扩展KMP又称Z函数,可以快速的求出一个字符串的每一个后缀的与其的LCP(最大公共前缀)长度。

至于为什么要学习exKMP,因为(数据规模很上进)我们都是上进的OIer。

算法思路

暴力朴素的算法

\(n\)个字符的字符串S中第\(i\)位开始的后缀与S的开头一一比较,求出LCP数组Z。

CODE

for(int i=1;i<n;i++)
{while(z[i]+i<n&&s[z[i]]==s[z[i]+i]) z[i]++;
}

由于上述算法太朴实无华了,所以我们的时间复杂度也很朴实无华达到\(O(n^2)\)

exKMP

为了解决上述过分朴实无华的时间复杂度,exKMP学会了剥削利用一切可以利用的数据。

在exKMP中,我们从\(1\)\(n-1\)依次计算z数组,那么我们在计算\(z[i]\)\(z[1,i-1]\)是已经计算好了的。我们在计算过程中维护一个\(r\),使\(r=max(z[j]+j-1)(j \lt i)\),同时使\(l\)等于这个区间的左端点,即\(j\)。(\(r,l,j\)如图)

由z数值的定义可知,\(S[l,r]\)段是从第\(l\)位开始的字符串\(S\)的后缀与字符串\(S\)的LCP。那么\(S[0,z[l]-1]=S[l,r]\)。因为\(r=z[l]+l-1\),所以\(S[0,r-l]=S[l,r]\),且\(S[z[l]]!=S[r+1]\)(如果等于,那么z[l]就不是最大的)。(如图)

举个例子:
S={aaabb}(i=0,4),当\(l=1\)时,\(z[l]=2,r=2\)。可以看出\(S[0,r-l]=S[l,r]\)

理解上面后,我们来计算\(z[i]\)

1.若\(l \lt i \leq r\),则\(S[i,r]=S[i-l,r-l]\)(上一个图所述情况可以看成\(i=l\)的情况,\(i\)每往后挪动一位,\(i-l\)也往后挪动一位)。

1.1若\(z[i-l] \lt r-l+1\),也就是如图蓝线所示部分:

因为\(S[i-l,r-l]=S[i,r]\),所以\(S[i-l,i-l+z[i-l]-1]=S[i,i+z[i-l]-1]\)。即上图中蓝红线所示部分相同。

而且\(S[i-l+z[i-l]] \neq S[i+z[i-l]]\)(上文有类似证明),所以\(z[i]=z[i-l+1]\)

1.2若\(z[i-l] \ge r-i+1\)时,使\(z[i]=r-i+1\),然后使用朴素的对比方法。(优质的食材往往使用最朴素的烹饪方法)(\(r\)以外的字符不清楚,那么就暴力查询)

2.若\(i \gt r\),朴素求\(z[i]\)

注意每次求出z[i]后都要看当前的z[i]是否可以更新l和r。

代码:

for(int i=1,l=0,r=0;i<m;i++)
{if(i<=r&&z[i-l]<r-i+1) z[i]=z[i-l];//1.1的情况else{z[i]=max(0,r-i+1);//1.2或2的情况对z[i]的更新while(i+z[i]<n&&b[z[i]]==b[i+z[i]]) z[i]++;//暴力求法}if(i+z[i]-1>r) l=i,r=i+z[i]-1;//更新l,r
}

exKMP的时间复杂度

虽然我们看似进行了很多次的朴素方法,但是我们使用暴力求法时都是\(i+z[i-l] \ge r\)\(i \gt r\)的时候,而且我们的\(r\)是不断向后变化的(不变化就一定是\(O(1)\)的解法),也就是说实际上我们只对\(S[]\)(也就是代码中的\(b[]\))只遍历了一次(对于整个exKMP来说,下同),而外围循环求\(z\)也只会遍历一次\(z\)。所以总时间复杂度\(O(n)\)

后记

如果是两个字符串要求z函数,我们把他们拼成一条字符串,并且在连接处增加一个不属于这两个字符串的字符,就可以回归上述做法。

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

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

相关文章

运算

模二加(异或)运算模 即取余 模运算 当两个整数 a 和 b 模 n 同余,记作 a≡b(mod n),意味着 a 和 b 被 n 除后余数相同。 基本性质:封闭性:如果 a≡b(mod n) 且 c≡d(mod n),那么 a+c≡b+d(mod n),以及 a⋅c≡b⋅d(mod n)。 乘法逆元:对于任何整数 a 和正整数 n,存在一…

Knapsack题解

题面下划线:符合单调性 举例:k=3W : 1 2 3 4 5V : 6 5 1 2 4g: 15 11 7 6 4

Win11安装基于WSL2的Ubuntu

详细介绍了Win11安装基于WSL2的Ubuntu的过程。1. 概述 趁着还没有完全忘记,详细记录一下在Win11下安装基于WSL2的Ubuntu的详细过程。不得不说WLS2现在被微软开发的比较强大了,还是很值得安装和使用的,笔者就通过WLS2安装的Ubuntu成功搭建了ROS环境。 2. 详论 2.1 子系统安装…

什么是芯片领域的敏捷设计(Agile Development)

芯片领域的敏捷设计是一种灵活的开发方法,致力于更快速、更高效地开发和优化集成电路(IC)和半导体技术。其核心特点包括:1、迭代开发;2、跨功能团队合作;3、客户反馈导向;4、及时响应变更。其中,迭代开发强调分阶段、小步快跑的设计方法,有助于快速地调整和优化设计。…

Clickhouse基本使用方法详细讲解(包括详细步骤及相关操作截图)

超详细ClickHouse学习笔记 一、ClickHouse概述 ClickHouse是一个用于在线分析处理查询(OLAP)的列式数据库管理系统(DBMS)。它由Altinity公司开发,支持线性扩展和高性能的数据压缩。ClickHouse以其卓越的数据处理速度而闻名,特别适合于大规模数据集的实时查询和分析。OLTP…

高ROI的行业或项目一般有什么样的特点

高ROI的行业或项目一般的特点有:1、市场需求的洞察;2、有效的成本控制;3、创新和技术应用;4、强大的市场定位;5、风险管理。实现高ROI的项目通常基于对市场需求的深刻洞察。这意味着项目管理者或企业家需要了解消费者的需求,预测市场趋势,并能够提供满足这些需求的产品或…

IDEA如何更改背景桌面图片

前言 我们在使用IDEA开发Java应用时,经常对着屏幕,有时候也感觉有点枯燥,这时候,就可以设置一个背景图片来缓解一下,比如说设置一张风景图片,或者设置一个美女图片,哈哈哈。 那么,我们可以如何设置呢? 如何设置 首先,我们打开设置面板。然后,我们点击下【Appearance…

灰色代码部分:要是输入名字列表,又能输出结果,但是空列表的时候就输出不了?

大家好,我是Python进阶者。 一、前言 前几天在Python白银交流群【Aciel】问了一个Python基础的问题,问题如下:灰色代码部分:要是输入名字列表,又能输出结果,但是空列表的时候就输出不了?二、实现过程 这里【瑜亮老师】给了一个指导,具体如下所示:@Aciel 循环 for nam…

assembly2

汇编2 寄存器(不同架构不同) 8086中寄存器均为16位,可存放两个字节(1byte=8bit)。 通用寄存器AX,BX,CX,DX用来存储一般性的数据,被称为通用寄存器。二进制数据在寄存器中是低位存在低地址,高位存在高地址。也可将一个寄存器分为H,L(高8位低8位)来做8位存储器。字在寄存器…

shctf[Week3] 小小cms

看到首页面 了解到YzmCMS的版本,上网搜搜这个版本存在的漏洞 发现存在任意函数调用RCE的漏洞 https://blog.csdn.net/shelter1234567/article/details/138524342 根据文章直接抄payload,进入/pay/index/pay_callback目录下下面cat /flag即可,最终的payload为 out_trade_no[0…

数据采集与融合技术实践作业二

作业①:7日天气预报爬取 1. 作业代码与实现步骤 我们将在中国气象网爬取北京、上海、广州的7日天气预报,并将数据保存到数据库中。以下是实现步骤。 步骤详解打开中国天气网:在浏览器中访问中国天气网。搜索城市:输入“北京”并打开其天气页面。检查网页结构:使用浏览器的…

clickhouse安装部署使用

一、安装 下载地址https://packages.clickhouse.com/rpm/stable/上传文件到Linux中开始安装1、进入到文件所在目录cd /usr/local/soft/clickhouse-rpms/2、使用rpm命令安装sudo rpm -ivh *.rpm3、查看状态systemctl status clickhouse-server4、启动服务systemctl start clickh…