【学习笔记】lyndon分解

摘抄自quack的ppt。

这部分和 s a sa sa的关联比较大,可以加深对 s a sa sa的理解。

Part 1

如果字符串 s s s的字典序在 s s s以及 s s s的所有后缀中是最小的,则称 s s s是一个 lyndon \text{lyndon} lyndon串。

lyndon \text{lyndon} lyndon分解,指的是把一个字符串分成若干段,每一段都是一个 lyndon \text{lyndon} lyndon串,问最少的分割段数。

方法一:用后缀数组 s a [ 1 ] sa[1] sa[1]就是 lyndon \text{lyndon} lyndon分解的最后那一段, lyndon \text{lyndon} lyndon分解倒数第二段就是把 s a [ 1 ] sa[1] sa[1]那一段排除之后排的最靠前的 s a sa sa,以此类推。

s a sa sa可以用来 lyndon \text{lyndon} lyndon分解依赖于以下结论:

定义数组 a [ i ] a[i] a[i]为最小的 j j j,使得 j > i j>i j>i S [ j : ∣ S ∣ − 1 ] < S [ i : ∣ S ∣ − 1 ] S[j:|S|-1]<S[i:|S|-1] S[j:S1]<S[i:S1],如果不存在这样的 j j j,可以认为 a i = ∣ S ∣ a_i=|S| ai=S

那么, S S S lyndon \text{lyndon} lyndon分解的第一项为 S [ 0 : a [ 0 ] − 1 ] S[0:a[0]-1] S[0:a[0]1],且后面 m − 1 m-1 m1项就是 S [ a [ 0 ] : ∣ S ∣ − 1 ] S[a[0]:|S|-1] S[a[0]:S1] lyndon \text{lyndon} lyndon分解。

证明:显然此时不能划分到 a [ 0 ] a[0] a[0]之后,否则可以根据原串后缀的信息道出矛盾。因此只需论证划分到 a [ 0 ] a[0] a[0]合法即可。注意到此时 S [ a [ 0 ] ] ≤ S [ 0 ] S[a[0]]\le S[0] S[a[0]]S[0],因此对于任意 j ∈ [ 1 , a [ 0 ] − 1 ] j\in [1,a[0]-1] j[1,a[0]1],一定满足 S [ 0 : a [ 0 ] − j − 1 ] ≠ S [ j : a [ 0 ] − 1 ] S[0:a[0]-j-1]\ne S[j:a[0]-1] S[0:a[0]j1]=S[j:a[0]1],又因为 s a [ 0 ] < s a [ j ] sa[0]<sa[j] sa[0]<sa[j],因此 S [ 0 : a [ 0 ] − 1 ] S[0:a[0]-1] S[0:a[0]1]一定是它的所有后缀当中最小的。

基本性质:

1.1 1.1 1.1 若字符串 u , v u,v u,v lyndon \text{lyndon} lyndon串且 u < v u<v u<v,则 u v uv uv lyndon \text{lyndon} lyndon串。

1.2 1.2 1.2 若字符串 s s s lyndon \text{lyndon} lyndon串, s ′ a s'a sa s s s的前缀,那么 s ′ b ( b > a ) s'b(b>a) sb(b>a) lyndon \text{lyndon} lyndon串。(注意 s ′ a s'a sa不一定是 lyndon \text{lyndon} lyndon串)

方法二:duval 算法

每次维护一个前缀的 lyndon \text{lyndon} lyndon分解。这个前缀 S [ 1 : k − 1 ] S[1:k-1] S[1:k1]可以被分解成 s 1 , . . . , s g s_1,...,s_g s1,...,sg这些 lyndon \text{lyndon} lyndon串和 S [ i : k − 1 ] S[i:k-1] S[i:k1]这个近似 lyndon \text{lyndon} lyndon串(形如 w k w ′ w^kw' wkw w w w是一个 lyndon \text{lyndon} lyndon串, w ′ w' w w w w的前缀)。

具体的,三个变量 i , j , k i,j,k i,j,k维持一个循环不变式:

  • S [ 0 : i − 1 ] = s 1 s 2 . . . s g S[0:i-1]=s_1s_2...s_g S[0:i1]=s1s2...sg 是已经固定下来的分解,满足 s l s_l sl lyndon \text{lyndon} lyndon串,且 s l ≥ s l + 1 s_l\ge s_{l+1} slsl+1(否则可以合并)。
  • S [ i : k − 1 ] = t 1 t 2 . . . t h v S[i:k-1]=t_1t_2...t_hv S[i:k1]=t1t2...thv是没有固定的分解,满足 t 1 t_1 t1 lyndon \text{lyndon} lyndon串, t 1 = t 2 = . . . = t h t_1=t_2=...=t_h t1=t2=...=th v v v t h t_h th的(可为空的)真前缀,令 j = k − ∣ t 1 ∣ j=k-|t_1| j=kt1

在这里插入图片描述

复杂度为 O ( n ) O(n) O(n)比sa快啊

代码

Part 2

lyndon \text{lyndon} lyndon分解的应用:

1.3 1.3 1.3 给定长为 n n n的字符串 S S S,求出 S S S的最小表示法。

方法:将 S S SS SS lyndon \text{lyndon} lyndon分解,找到分解后最后一个字符串,它的首字符为 S S [ p ] SS[p] SS[p],且 p ∈ [ 0 , ∣ S ∣ ) p\in [0,|S|) p[0,S)。可以证明 S S [ p : p + ∣ S ∣ − 1 ] SS[p:p+|S|-1] SS[p:p+S1]是字典序最小的。(运用第一条引理,转化为比较在原串中的后缀,即sa)

1.4 1.4 1.4 给定长度为 n n n的字符串 S S S,将 S S S分为最多 k k k个串 c 1 c 2 . . . c k c_1c_2...c_k c1c2...ck,求 max ⁡ c i \max c_i maxci的最小值。

方法:看到字典序,容易想到 lyndon \text{lyndon} lyndon分解。首先把 S S S lyndon \text{lyndon} lyndon分解成 s 1 , . . . , s g s_1,...,s_g s1,...,sg,如果 k ≥ g k\ge g kg,那么答案即为 s 1 s_1 s1;否则,如果 s 1 > s 2 s_1>s_2 s1>s2,那么显然可以分成 s 1 s_1 s1和剩下的所有串,答案还是 s 1 s_1 s1。因此,考虑分解成 s 1 m s g s_1^ms_g s1msg的情况,如果 k > m k>m k>m,那么答案还是 s 1 s_1 s1,如果 k ≤ m k\le m km,那么尽量均分一下即可。

推广:多次询问,每次询问 S S S的一段后缀的答案。

考虑求出原串的sa数组,显然可以求出第一项以及重复次数(可以用哈希),这样就做完了。

1.5 1.5 1.5 S S S的每个前缀的字典序最小的后缀

首先把 S S S lyndon \text{lyndon} lyndon分解成 s 1 , . . . , s g s_1,...,s_g s1,...,sg,显然 s 1 . . . s k s_1...s_k s1...sk的字典序最小的后缀是 s k s_k sk。但是前缀取到分解出来的 lyndon \text{lyndon} lyndon串半截时,答案可能不一样。

考虑 duval \text{duval} duval算法求 lyndon \text{lyndon} lyndon分解的过程,分类讨论:

  • s [ k ] > s [ j ] s[k]>s[j] s[k]>s[j],此时 a n s [ k ] ans[k] ans[k]应该等于 i i i,因为 s [ i : k ] s[i:k] s[i:k]构成一个新的 lyndon \text{lyndon} lyndon
  • s [ k ] = s [ j ] s[k]=s[j] s[k]=s[j],此时 a n s [ k ] = a n s [ j ] + k − j ans[k]=ans[j]+k-j ans[k]=ans[j]+kj
  • s [ k ] < s [ j ] s[k]<s[j] s[k]<s[j],在 lyndon \text{lyndon} lyndon串开头时更新

1.6 1.6 1.6 S S S的每个前缀的字典序最大的后缀

首先把字符比较反过来,然后要尽量向左取,当 s [ k ] ≤ s [ j ] s[k]\le s[j] s[k]s[j]的时候, s [ i : k ] s[i:k] s[i:k]这一段都保持了是一个近似 lyndon \text{lyndon} lyndon串,所以都取近似 lyndon \text{lyndon} lyndon串的左端点 i i i作为答案即可。

ps:感觉这个算法就只能考论文题。。。太恶心了。。。

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

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

相关文章

c++ 类和对象-封装意义一

属性和行为作为整体 示例一&#xff1a;设计一个圆类&#xff0c;求圆的周长 #include<iostream> using namespace std; //圆周率 const double PI 3.14; //设计一个圆类&#xff0c;求圆的周长 //圆求周长的公式&#xff1a;2*PI*半径 //class代表设计一个类&#xf…

熔池处理Tecplot 360 和CFD-Post做出一样的效果

熔池处理Tecplot 360 和CFD-Post做出一样的效果 效果展示详细讲述Tecplot 360实现过程分析实现过程第一步实现过程第二步界面美化注意点效果展示 详细讲述Tecplot 360实现过程 分析 这里主要是将体积分数大于0.5的区域抽取出来,然后显示温度场,所以这里主要考虑下面连个思考…

PCL 三维点云中求解圆的三维方程

一、概述 在给出的三维点云中求解拟合圆的三维方程 二、代码示例 #include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/sample_consensus/ransac.h> #include <pcl/sample_consensus/sac_model_circle3D.h> // 拟

【贪心算法】 Opponents

这道题写伪代码就好了&#xff01; Description Arya has n opponents in the school. Each day he will fight with all opponents who are present this day. His opponents have some fighting plan that guarantees they will win, but implementing this plan requires pr…

【开源】基于Vue+SpringBoot的固始鹅块销售系统

项目编号&#xff1a; S 060 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S060&#xff0c;文末获取源码。} 项目编号&#xff1a;S060&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 鹅块类型模块2.3 固…

Mybatis-plus中wrapper的区别

在MyBatis-Plus框架中,LambdaQueryWrapper 和 QueryWrapper 是用于构建查询条件的两个主要类。它们都是查询条件构造器,用于在查询中生成 WHERE 子句的条件。 QueryWrapper QueryWrapper 是 MyBatis-Plus 3.x 中引入的条件构造器。它的主要特点是使用字符串作为字段名,并支…

python 数字保留小数位数 结果是字符串

precision 2 f{px :.{precision}f} # 自定义动态 f{x:.2f} 数字 转 字符串 保留dot后面的位数 结果 字符串

从关键新闻和最新技术看AI行业发展(2023.11.20-12.3第十一期) |【WeThinkIn老实人报】

Rocky Ding 公众号&#xff1a;WeThinkIn 写在前面 【WeThinkIn老实人报】旨在整理&挖掘AI行业的关键新闻和最新技术&#xff0c;同时Rocky会对这些关键信息进行解读&#xff0c;力求让读者们能从容跟随AI科技潮流。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&…

MySQL概述-安装与启动

数据库相关概念 MySQL数据库 下载地址 MySQL :: Download MySQL Installer (Archived Versions) 启动方法 启动密令&#xff1a;net start mysql80 停止密令&#xff1a;net stop mysql80 客户端链接方法 注意用系统自带的命令行工具执行指令需要设置环境在高级系统设置中…

解决使用pnpm安装时Sharp模块报错的方法

在使用pnpm进行项目依赖安装的过程中&#xff0c;有时候会遇到Sharp模块报错的情况。Sharp是一个用于处理图像的Node.js模块&#xff0c;但它的安装可能会因为各种原因而失败&#xff0c;导致项目无法正常启动。本文将介绍这个问题的方法。 问题描述 解决方法 在命令行分别输…

Linux-帮助命令的使用和练习(type、man、help、info详解)

目录 5.3.1 type-判断是否为内部命令 5.3.2 man-查看详细文档 5.3.3 help-查看shell内部命令的帮助信息 5.3.4 --help-查看系统外部命令帮助信息 5.3.5 info-查看info格式的帮助指令 5.3.6 /usr/share/doc-存储软件包的文档信息 平时我们看到的命令大多数都可以查看帮助文…

NTP反射放大攻击

文章目录 什么是NTPNTP反射放大攻击解决方案搭建NTP服务器部署服务器端windows NTP命令行本机测试 部署客户端ntpdatechrony 实验Python利用脚本 什么是NTP 基于UDP协议的NTP&#xff08;网络时间协议&#xff09;&#xff1a;使网络中各个计算机时间同步的一种协议 用途&…

vue3-vite前端快速入门教程 vue-element-admin

Vue3快速入门学习 初始化项目 # 创建项目 npm create vitelatest my-vue-app -- --template vue # 安装依赖 npm i # 运行 npm run dev 模板语法 文本插值​ 最基本的数据绑定形式是文本插值&#xff0c;它使用的是“Mustache”语法 (即双大括号)&#xff1a; <span&g…

【数据结构】——排序篇(中)

前面我们已经了解了几大排序了&#xff0c;那么我们今天就来再了解一下剩下的快速排序法&#xff0c;这是一种非常经典的方法&#xff0c;时间复杂度是N*logN。 快速排序法&#xff1a; 基本思想为&#xff1a;任取待排序元素序列中的某元素作为基准值&#xff0c;按照该排序码…

C++ queue 和priority_queue

目录 1.什么是queue 2.模拟实现 3.仿函数 模板参数Compare 仿函数 4.什么是priority_queue 模拟实现 1.什么是queue 1.队列是一种容器适配器&#xff0c;专门用于在FIFO上下文(先进先出)中操作&#xff0c;其中从容器一端插入元素&#xff0c;另一端提取元素。 2.队列作为…

Java转Go学习之旅 | Go入门(1)

入门 命令行参数找出重复行常规版本涉及文件操作 命令行参数 命令行参数以os包中Args名字的变量供程序访问&#xff0c;在os包外面&#xff0c;使用os.Args这个名字 变量os.Args是一个字符串sliceos.Args[0]&#xff1a;命令本身的名字os.Args[1:]&#xff1a;另外的元素&…

Cglib动态代理从入门到掌握

Cglib 动态代理 本文的写作目的是为了探究 Spring 框架中在使用Transactional标注的方法中使用 this 进行自调用时事务失效的原因&#xff0c;各种视频教程中只是简单指出 this 指向的不是代理类对象&#xff0c;而是目标类对象&#xff0c;但是并没有解释为什么 this 不是代理…

麒麟系统使用桌面共享远程桌面

客户端安装vinager 服务端 安装 vnc4server xrdp tightvncserver vino 安装完成后 需要重启 在用户的家目录下新建 .xsession 写入xfce4-session防止闪退 雪花屏 开启xrdp服务 远程链接 Vnc只能链接系统登录的用户 Rdp可以链接所有普通用户

vscode插件webview和插件通信

如果你要在 VS Code 插件的 WebView 中调用插件中的方法&#xff0c;可以使用 vscode.postMessage API。具体步骤如下&#xff1a; 在插件中&#xff0c;在创建 WebView 时&#xff0c;指定一个 onDidReceiveMessage 回调方法&#xff0c;该方法会在 WebView 中调用 vscode.po…

【C语言】结构体内存对齐

目录 引入结构体 结构的声明 创建和初始化 内部元素的使用&#xff1b; 特殊声明&#xff1a; 结构体在内存中的对齐 练习&#xff1a; 引入结构体 C语言有各种数据类型&#xff0c;我们已经对一些数据类型很熟悉&#xff1a; 整型&#xff08;int&#xff09;- 存储整…