lyndon分解! 2020杭电多校1 1011 Minimum Index

本文介绍了如何使用Lyndon分解解决2020杭电多校1 1011题,详细阐述了Lyndon串的概念、Duval算法以及解题思路,通过代码实现解释了如何找到每个前缀中字典序最小的后缀起始位置。
摘要由CSDN通过智能技术生成

学到了个新的操作,调题目调了好久,但是很有意思,分享一哈。

题目大意

题目链接在此
在这里插入图片描述
大致意思就是给定T个字符串,每个字符串尤其长度个数量的前缀,求其每个前缀中字典序最小的后缀的起始位置,并将他们乘上1112的幂加起来对1e9 + 7取模。

题目不难理解,但就是每个字都看懂了,连起来就是不会或者说没有思路。要解决这个问题,一种可行的方法是借助lyndon分解,下面我们就先来看一下lyndon分解是何方神圣。

lyndon分解

介绍lyndon分解前,我们需要先了解一个概念:lyndon串

对于字符串 ,如果 的字典序严格小于 的所有后缀的字典序,我们称 是简单串,或者 Lyndon 串 。也就是说对于一个lyndon串来说,字典序最小的后缀就是其本身。像aaabbaabab等都是lyndon串。

所谓lyndon分解,就是将一个字符串分解成为若干连续的lyndon子串。这些字串满足非严格的单调递减的字典序。也就是说,允许存在相邻的lyndon串相同,但是不允许出现排在后面的lyndon串比前面的串小。这点不难说明,我们假设有lyndon串 si 和 si+1 ,假设

si < si+1

那么容易说明sisi+1也是一个lyndon串,分解时应直接生成sisi+1而非两个字串,因此不会出现上述情况。可以发现,这样的费解存在且唯一。

Duval算法

进行lyndon分解,可以使用Duval算法进行处理,这里简述一下这个算法过程,具体的过程可以参考 IO Wiki Lyndon分解

Duval算法采用贪心的思想,将一个字符串分成三个部分,即:已分解s1,正在处理s2,未处理s3,将字符一个一个处理。因此整个字符串S=s1s2s3

使用三个下标i j k标记字符串,其中i表示s2的起始位置,j表示s3的起始位置即新加入的字符,k代表着j位字符在s2上一个循环节对应的字符。

每一次,若
s[j] == s[k],意味着j对应着s2某个循环节的一个字符,拼在s2的末尾使得其仍满足其近似简单性,使j k同时向后移动一步。例如s2=aab,s[j] = a,s[k] = a

s[j] > s[k],意味着循环节失效,新的字符直接拼到s2的末尾,使得新的s2整体就是一个lyndon串,例如:abab ---> ababc,此时让k = i,j++

s[j] < s[k],此时s[j]拼在s2的末尾就会影响其简单性了,那么就不能继续添加,转而应该将s2中现有的lyndon串全部分解出来变成s1的一部分,其中的lyndon串就是完整的循环节剩下的继续上面的过程。例如,abbabbab + a --> abb|abb| ab + a前面两个abb就是已经可以确认的lyndon串。但是后面剩下的ab就不是lyndon串了。不难发现,完整的lyndon串的起始位置都小于等于k且长度为j - k

代码实现:

#include<iostream>
#include<string>
#include<vector>
using namespace std;

vector<string> duval(string str){
   
	int i = 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值