首页 > 编程语言 >Z 算法 学习笔记

Z 算法 学习笔记

时间:2024-05-26 10:33:20浏览次数:23  
标签:匹配 暴力 text 位置 笔记 学习 算法 字符串

问题引入

寻找字符串 \(T\) 在字符串 \(S\) 中的出现位置。


暴力算法

暴力枚举 \(S\) 的每一位作为开头,向后匹配,若能将 \(T\) 匹配完毕就为 \(T\) 在 \(S\) 中的一次出现。

记 \(S\) 的长度为 \(n\),\(T\) 的长度为 \(m\),则时间复杂度最劣为 \(O(nm)\)。


优化

上面的算法有很多冗余计算,具体表现在某次匹配失败就直接从下一位继续匹配,实际上在上次匹配失败的过程中,我们已经获得了 \(S\) 上后面一段的信息,可以借助此信息去掉很多无用的尝试。

比如 \(S= \text{happened}\),\(T= \text{happy}\),当从第一位开始匹配,到第五位失配,可以知道 \(S[1,5]= \text{happe}\) ,因此可以知道 \(T\) 不会在 \([2,4]\) 出现。

因此可以先对 \(T\) 做一些处理获得一些信息来帮助优化这种情况。


算法流程

将 \(T\) 和 \(S\) 中间加一个特殊符号分隔符拼在一起,记为 \(A\),计算 \(z_i\) 表示 \(A[1,len]\) 和 \(A[i,len]\) 的 LCP 长度。

由于分隔符的存在,前 \(|T|\) 个位置的 \(z_i\) 不会等于 \(T\),后面的位置的 \(z_i\leq |T|\),所有 \(z_i=|T|\) 的位置刚好可以匹配成功 \(T\),就是 \(T\) 的所有出现位置。

现在的问题就变成了如何快速计算 \(z\) 数组,显然我们希望借助前面的 \(z_i\) 的一些信息计算当前位置。

每个位置 \(i\),\(A[i,i+z_i-1]\) 是以它开头的字符串与前缀的 LCP,定义这个字符串为 \(Z-box\)。

考虑维护 \(l,r\) 表示目前找到的最靠右(右端点最大)的 \(Z-box\) 左右端点,此时已知 \(z_{1}-z_{i-1}\),要求 \(z_i\),分为以下几种情况:

  1. \(i>r\),直接从 \(i\) 开始暴力匹配前缀,\(z_i\) 为匹配的长度,\(l,r\) 更新为 \(i,i+z_i-1\)。

  2. \(i \leq r\)
    2.1 \(z_{i-l+1} \leq r-i+1\),\(z_i=z_{i-l+1}\),\(l,r\) 不变。
    2.2 \(z_{i-l+1} > r-i+1\),先令 \(z_i=r-i+1\) ,然后继续匹配前缀更新 \(z_i\),并将 \(l,r\) 更新为 \(i,i+z_i-1\)。

情况二的解释如下图(图自己画的有点丑):


复杂度分析

首先需要从头到尾扫一遍字符串。

在不用暴力匹配的时候,直接计算是单次 \(O(1)\),如果需要暴力匹配一定会向右移动 \(r\),且 \(r\) 的移动是单调的,因此 \(r\) 移动(即暴力匹配)的总时间是 \(O(n)\) 的。

因此这个匹配算法是线性的。

标签:匹配,暴力,text,位置,笔记,学习,算法,字符串
From: https://www.cnblogs.com/wonderfish/p/18213398

相关文章

  • 局部直方图均衡化去雾算法
    目录1.引言2.算法流程3.代码4.去雾效果1.引言        局部直方图算法是一种基于块的图像去雾方法,它将图像分割为若干个块,并在每个块内计算块的局部直方图。通过对各个块的直方图进行分析和处理,该算法能够更好地适应图像中不同区域的光度差异和雾霾密度变......
  • 滑不动窗口的秘密—— “滑动窗口“算法 (Java版)
    本篇会加入个人的所谓鱼式疯言❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言而是理解过并总结出来通俗易懂的大白话,小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.......
  • 【升级版本】基于多目标粒子群算法的微电网优化调度【风光、储能、柴油、燃气、电网交
     ......
  • 113文章解读与程序——电力系统保护与控制EI\CSCD\北大核心《改进多元宇宙算法的主
    ......
  • 基于Kaggle学习MONAI(三)2D-Segmentation例程代码详解1
    1简介         MONAI网站提供了2D分类/分割、3D分类/分割等例程代码如下图所示,通过学习例程代码,初学者能够尽快掌握MONAI框架,但是由于开源框架软件版本更新较快、各模块功能难以协调等原因,这些例程往往无法在Kaggle平台直接运行。本文对MONAI官网第二个例程,即2D分割......
  • 机器学习 - toad库
    toad是一个Python库,用于数据预处理和特征工程,特别是在金融风控和信用评分建模中应用广泛。以下是toad库中主要函数的详细说明,包括它们的参数和作用:数据转换与预处理1.toad.transformer.WOETransformer作用:将分类变量转换为WOE(WeightofEvidence)值,以便更好地用于模......
  • 关于对于Java中Entity以及VO,以及DTO中Request对象序列化的学习
    关于Serializable的探讨前提引入是由于软件测试上有同学提到说,什么该字段在程序刚运行时,导致jvm激增,所以吸引了我的注意回顾代码MybatisPlusGenerator自动生成的entity中就经常带有这个,而且我在开发代码的时候VO,以及DTO常常是直接复制对应的entity,所以也保不齐我对应......
  • 【python】requests库学习
    一、GET请求1、当使用requests.get(url)方法发送GET请求时,它会向指定的URL发送一个HTTPGET请求,并返回一个包含服务器响应的Response对象。例如:​url="https://api.example.com/data"response=requests.get(url)2、添加URL参数:可以通过将参数作为字典传递给params参数......
  • 视差背景,GODOT游戏引擎学习笔记(五)
    背景图片资源今天周六玩了一天,现在晚上来更新一下帖子。前面几节我们学习了创建一个人物精灵节点使其移动。这节我们来学习创建背景。会用到三个图片文件。我已经上传到csdn了,链接如下:https://download.csdn.net/download/weixin_66990397/89356894?spm=1001.2014.3001.5501......
  • 开坑开坑,GODOT游戏引擎学习笔记(一)
    前言         本人重度游戏玩家,计科专业学生,玩了许多游戏已经逐渐电子羊尾,于是打算学习几个游戏引擎,一个方面是爱好,另一方面也是多掌握点技术。先打算从2D游戏开始学,目前引擎确定为GODOT,一个开源且适合新手的引擎。后续学习unity和虚幻等引擎也会继续更新,同时也会开......