Z Algorithm(扩展KMP)算法笔记

假设给定一个s长度为的n字符串。那么这个字符串的 z-function (“zet-function”)是一个长度为 的数组,其中的 -th 元素等于最大字符数,从 position i开始,i与字符串的第一个字符n重合。

换句话说,z[i]它是s字符串及其i-th 后缀的最大通用前缀。

注意:在本文中,为了避免歧义,我们将字符串视为0索引,即字符串的第一个字符具有索引0,最后一个n-1字符是。

z 函数的第一个元素通常z[0]被认为等于零。

本文描述了一种计算z函数的O (n)算法,以及该算法的各种应用。

例子

下面是针对多个计算的 z 函数的示例:

  • aaaaa
z[0] = 0,
z[1] = 4,
z[2] = 3,
z[3] = 2,
z[4] = 1
  • aaabaaab
z[0] = 0,
z[1] = 2,
z[2] = 1,
z[3] = 0,
z[4] = 2,
z[5] = 1,
z[6] = 0
  • abacbaa
z[0] = 0,
z[1] = 0,
z[2] = 1,
z[3] = 0,
z[4] = 3,
z[5] = 0,
z[6] = 1

朴素算法

以下算法基本实现时间复杂度O (n^2):

    public static int[] zFunction(String s){
        int n=s.length();
        char[]sa=s.toCharArray();
        int[] z=new int[n];
        for(int i=1;i<n;i++){
            while(i+z[i]<n&&sa[z[i]]==sa[i+z[i]]){
                ++z[i];
            }
        }
        return z;
    }

对于每个位置i,我们只需从零开始迭代它的z[i]答案,直到我们发现不匹配或到达线的末尾。

计算 z 函数的有效算法

为了获得有效的算法,我们将逐个计算值,从i=1到,同时在计算下一个值时,我们将尝试n-1充分利用已经计算出的值z[i]。

为简洁起见s,我们将与字符串前缀匹配的子字符串称为匹配栏。例如,您要查找的z函数z[i]的值是从position开始(并将在positioni,i+z[i]-1结束)的最长匹配段。

为此,我们将保持重合最[左;r]右边段的坐标,即我们将存储在所有检测到的段的右侧结束的坐标。从某种意义上说,索引r是算法已经扫描了我们的字符串的边界,其他一切都还不知道。

然后,如果我们要计算z函数的下一个值的当前索引是i,我们有以下两个选项之一:

  • i>r—换句话说,目前的情况超出了我们已经处理的情况。
    然后我们将使用一个简单的算法进行搜索z[i],即只尝试、等的值z[i]=0。请注意,最后,如果z[i]结果是,z[i]=1那么我们将不得不更新最右边段[左;r]的坐标——因为它i+z[i]-1保证>0大r于。

  • i≤r—即当前位置位于重合段[左;r]内。
    在这种情况下,我们可以使用已经计算出的z函数的先前值来初始化值,而不是用零,而是用一些可能更高的数字来初始化值z[i]。

为此,请注意子字符串s[l…r]重合s[0…r-l]。这意味着作为初始近似值,z[i]我们可以从直线中获取相应的值,即s[0…r-l]值z[i-l]。

但是,该值z[i-l]可能太大,以至于当应用于某个位置我时,它会“爬出”边界r。这是不允许的,因为我们对右边的符号一无所知,而且它们可能与所需的符号r不同。

让我们举一个这种情况的例子,使用以下行作为示例:

aaaabaa

当我们到达最后一个位置i=6时,当前最右边的行是[5:6]。考虑到此段,该位置将对应6,6-5=1于答案等于z[1]=3的位置。显然,你不能用这样的值初始化z[6],这是完全不正确的。我们可以初始化的最大值是,因为它是1不超过[左;r]行的最大值。

因此,仅z[i]采用以下表达式作为初始近似值是安全的:

z_0[i]=min(r-i+1,z[i-l])。

使用z[i]这样的值初始化后,我们再次使用一个简单的算法,因为在边界之后,一般来说,可以找到z_0[i]线段的延续r,这是我们无法仅用z函数的先前值来预测的巧合。

因此,整个算法由两种情况组成,实际上仅在初始值上有所不同:在第一种情况下,假设它等于零,在第二种情况下,它由根据z[i]指定公式的先前值确定。之后,算法的两个分支都简化为执行一个从指定的初始值立即开始的简单算法。

事实证明,该算法非常简单。尽管他们每个人都我以一种或另一种方式执行一个微不足道的算法,但我们通过获得一种在线性时间内工作的算法取得了重大进展。为什么会这样,在我们介绍算法的实现之后,我们将在下面考虑。

实现

    public static int[] zFunction(String s){
        int n=s.length();
        char[]sa=s.toCharArray();
        int[] z=new int[n];
        int left=0,right=0;
        for(int i=1;i<n;i++){
            if (i<=right){
                z[i]=Math.min(right-i+1,z[i-left]);
            }
            while(i+z[i]<n&&sa[z[i]]==sa[i+z[i]]){
                ++z[i];
            }
            if (i+z[i]-1>right){
                left=i;
                right=i+z[i]-1;
            }
        }
        return z;
    }

数组最初填充为z为0。假设当前最右边的重合部分等于[0;0],即一个故意的小部分,其中不会落i下

在循环中,我们首先使用上述算法来确定初始值z[i]——它要么保持为零,要么根据给定的i=1…n-1公式计算。

之后,执行一个简单的算法,试图尽可能地增加该值z[i]。

最后,如果需要[左;r]此更新,则更新匹配的当前最右边部分,即ifi+z[i]-1>r

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

APP专项测试方法总结

APP专项测试 1、网络测试 可使用抓包工具辅助网格测试推荐&#xff1a;fiddler&#xff0c;Charles 网络切换&#xff1a; 2G-3G-4G-wifi-网络信号差–无网 网络信号弱&#xff1a; 关注是否出现ANR、crash 2、中断测试 意外中断&#xff1a; 来电&#xff1b;短信&am…

不需英文基础也可以轻松学编程,中文编程开发工具免费版下载,编程工具构件箱之扩展控制面板构件用法

不需英文基础也可以轻松学编程&#xff0c;中文编程开发工具免费版下载&#xff0c;编程工具构件箱之扩展控制面板构件用法 一、前言 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 编程工具及实例源码文件下载可以点击最下方官网卡片——软件下载——常…

ShardingSphere 5.x 系列【3】分库分表中间件技术选型

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 前言2. My Cat3. ShardingSphe…

C++ 类与对象(下)

目录 1. 再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.3 explicit关键字 2. static成员 2.1 概念 2.2 特性 3.友元 3.1友元函数 3.2 友元类 4. 内部类 5.匿名对象 6.拷贝对象时的一些编译器优化 7. 再次理解类和对象 【本节目标】 1. 再谈构造函数 2. Static成员…

【产品升级】SmartPipe升级到版本2.0

在近一个月的攻关和测试下&#xff0c;SmartPipe软件轴线自动识别算法的性能大幅提升&#xff0c;鲁棒性和稳定性进一步增强。近一年来客户累计反馈的多种复杂管路&#xff08;包括带有支管管路、带有压瘪段管路、推弯管、装配管、带有复杂孔洞管路等&#xff09;现在均能够正确…

通过消息队列实现进程之间通信代码

#include <myhead.h> struct msgbuf {long int mtype; char mtext[1024]; }; //定义一个消息大小 #define MSGSIZE sizeof(struct msgbuf)-sizeof(long int) int main(int argc, const char *argv[]) {//1、创建key值以便创建消息队列key_t key ftok("/", k)…

Bootstrap5 图片轮播

Bootstrap5 轮播样式表使用的是CDN资源 <title>亚丁号</title><!-- 自定义样式表 --><link href"static/front/css/front.css" rel"stylesheet" /><!-- 新 Bootstrap5 核心 CSS 文件 --><link rel"stylesheet"…

STM32WLE5JC

Sub-GHz 无线电介绍 sub-GHz无线电是一种超低功耗sub-GHz无线电&#xff0c;工作在150-960MHz ISM频段。 在发送和接收中采用LoRa和&#xff08;G&#xff09;FSK调制&#xff0c;仅在发送中采用BPSK/(G)MSK调制&#xff0c;可以在距离、数据速率和功耗之间实现最佳权衡。 这…

freeswitch对接FunASR实时语音听写

1、镜像启动 通过下述命令拉取并启动FunASR软件包的docker镜像&#xff1a; sudo docker pull \registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-online-cpu-0.1.7 mkdir -p ./funasr-runtime-resources/models sudo docker run -p 10096:10095 -i…

【Gephi项目实战-带数据集】利用gephi绘制微博肖战超话120位用户关系图,并计算整体网络指标与节点指标

数据集在评论区&#xff0c;B站演示视频在评论区&#xff01; 简介 最近2天需要用到gephi做社会网络分析&#xff0c;于是从0开始接触gephi并摸索出了gephi的基本使用指南。下面将结合真实的节点文件与边文件&#xff0c;利用gephi绘制社会网络并计算相关测量指标。整个过程会…

我们都是宇宙的奇迹

我们都是独一无二的个体&#xff0c;是宇宙的奇迹 如果我不关注自我&#xff0c;那我在这个宏大的宇宙中有什么意义&#xff1f; 关于你的问题&#xff0c;我想没有一个简单的答案&#xff0c;因为不同的人可能有不同的看法和感受。有些人可能认为&#xff0c;如果不关注自我&…

jbdc的简单了解

JDBC JDBC所处的位置 JDBC的本质 Java操作数据库的一套接口。 补充 ddl:数据库定义语言,例如建表,创建数据库等。 dml:数据库操作语言,例如增删改。 dql:数据库查询语言,例如查询语句。 注意 在创建Java项目后的第一个步骤是导入jar包。 导入jar包的步骤 1 创建l…

【C语言】const修饰指针的不同作用

目录 const修饰变量 const修饰指针变量 ①不用const修饰 ②const放在*的左边 ③const放在*的右边 ④*的左右两边都有const 结论 const修饰变量 变量是可以修改的&#xff0c;如果把变量的地址交给⼀个指针变量&#xff0c;通过指针变量的也可以修改这个变量。 但…

TCP/IP详细介绍以及TCP/IP寻址

目录 ​编辑 1. TCP/IP 介绍 2. 计算机通信协议&#xff08;Computer Communication Protocol&#xff09; 3. 什么是 TCP/IP&#xff1f; 4. 在 TCP/IP 内部 5. TCP 使用固定的连接 6. IP 是无连接的 7. IP 路由器 8. TCP/IP 9. TCP/IP 寻址 10. IP地址 …

LeetCode、1137. 第 N 个泰波那契数【简单,动态规划】

文章目录 前言LeetCode、1137. 第 N 个泰波那契数【简单&#xff0c;动态规划】题目与分类思路一维动态规划 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术…

记录下ibus-libpinyin输入法的重新安装

目前的版本为: 首先把现在的ibus-libpinyin卸了 sudo apt-get --purge remove ibus-libpinyin sudo apt-get autoremove 安装教程请参考 Installation libpinyin/ibus-libpinyin Wiki GitHub yilai sudo apt install pkg-config sudo apt-get install libglib2.0-de…

02-Web应用_架构构建_漏洞_HTTP数据包_代理服务器

Web应用_架构构建_漏洞_HTTP数据包_代理服务器 一、网站搭建前置知识1.1 域名1.2、子域名1.3、DNS二、web应用环境架构类三、web应用安全漏洞分类四、web请求返回过程数据包 五、演示案例5.1、架构-Web应用搭建-域名源码解析5.2、请求包-新闻回帖点赞-重放数据包5.3、请求包-移…

内网远程控制——向日葵

针对向日葵的话其实如果有本地安装的话&#xff0c;是有可能存在漏洞的。这里进行复现 攻击过程&#xff1a; 向日葵&#xff08;不可以攻击&#xff09; 遇到不可以攻击的向日葵&#xff0c;我们也有几种渗透手法&#xff1a; &#xff08;1&#xff09;窃取配置文件来进行解…

【八大排序】选择排序 | 堆排序 + 图文详解!!

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构冒险记 ✅C语言进阶之路 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 一、选择排序1.1 基本思想1.2 算法步骤 动图演示1.3 代码实现1.4 选择排序特性总结 二…

【开源】SpringBoot框架开发农村物流配送系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统登录、注册界面2.2 系统功能2.2.1 快递信息管理&#xff1a;2.2.2 位置信息管理&#xff1a;2.2.3 配送人员分配&#xff1a;2.2.4 路线规划&#xff1a;2.2.5 个人中心&#xff1a;2.2.6 退换快递处理&#xff1a;…