Lyndon分解和最小循环表示学习

做CF594E涉及的两个知识点。以下字符串采用Python记法。

Lyndon分解

定义 $S$ 是Lyndon串,当且仅当对于任意有意义的正整数 $i$ 有 $S<S[i:]$.

定义 $S$ 的Lyndon分解是一个Lyndon串的序列 $s_1, s_2, \ldots, s_n$, 使得 $S=s_1s_2 \cdots s_n$ 并且 $s_1 \ge s_2 \ge \cdots \ge s_n$.

Lyndon分解存在且唯一。

不难发现,Lyndon分解可以这么得到:对于 $S$, 取最小的后缀 $S[i:]$, $S$ 的Lyndon分解,是在 $S[:i]$ 的Lyndon分解的最后加上一项 $S[i:]$ 得到的序列。

于是,Lyndon分解可以用后缀数组求,但是这样太复杂了。

Lyndon分解的Duval算法:

设原字符串为 $S$. 逐个加入字符,设已能确定 $S[:i]$ 的Lyndon分解 $s_1, s_2, \ldots, s_n$ 为 $S$ 的Lyndon分解的前缀,再尽可能地扩充字符串 $S[i:k]$, 使得 $S[i:k]$ 具有Lyndon周期 $t$, 也就是说,$S[i:k]=(n \times t)u$, 其中 $u$ 是 $t$ 的(可以为空的)前缀,且 $t$ 是Lyndon串。考虑加入字符 $S_k$, 若 $k=|S|$ 则令 $S_k=-\infty$.

  • 若 $S_k<S_{k-|t|}$, 则 $S[i:k+1]$ 就没有Lyndon周期了。不过此时 $S[:i+n|t|]$ 的Lyndon分解已确定,即在 $S[:i]$ 的基础上加入 $n$ 个 $t$, 取新参数 $i‘=i+n|t|, k‘=i‘+1$ 重来。
  • 若 $S_k=S_{k-|t|}$, 则 $t$ 也是 $S[i:k+1]$ 的Lyndon周期。
  • 若 $S_k>S_{k-|t|}$, 则 $S[i:k+1]$ 的Lyndon周期是其本身。

实现上我们只需要维护 $i, k$ 以及 $j=k-|t|$. 代码链接

扩充 $S[i:k]$ 的过程中 $i+k\le2|S|$ 且随扩充总轮数递增,因此该算法时间 $O(|S|)$, 除去输入输出只需要 $O(1)$ 额外空间,是一个非常简短而高效的算法。

最小循环表示

最小循环表示,也就是对于字符串 $S$, 求出最小的 $S_i=S[i:]S[:i]$.

我们维护两个决策 $i, j$, 满足 $i<j$ 并且 $[0, i)$ 和 $(i, j)$ 中的整数都不是最优决策。

初始时,设 $i=0, j=1$.

我们通过枚举比较求出 $S_i$ 和 $S_j$ 的最长公共前缀 $k$.

  • 若 $S_i=S_j$, $S_i$ 即为最优解。这是因为,字符串以 $j-i$ 为循环节循环,而 $(i, j)$ 中任何整数都不是最优决策。
  • 若 $S_i<S_j$, 说明 $[j, j+k]$ 内的整数不是最小循环表示,因为它总比 $[i, i+k]$ 内的对应决策劣,因此令 $j \gets j+k+1$. 此时上述性质未改变。
  • 若 $S_i>S_j$, 同理令 $i \gets i+k+1$, 若 $i \ge j$ 则令 $j \gets i+1$, 上述性质仍未改变。

当 $j \ge |S|$ 时,我们发现 $[0, i)$ 和 $(i, |S|)$ 中的整数都不可能为最小决策了,所以 $S_i$ 是唯一的最优解;否则重复此过程。

$i+j+k \le 3|S|$ 随枚举总次数递增,因此该算法时间 $O(|S|)$, 除去输入输出只需要 $O(1)$ 额外空间,是一个非常简短而高效的算法。

1 int n=strlen(s), cho=0;
2 for(int i=1, j=0; cho<l&&i<l&&j<l; ) {
3     int t=s[(cho+j)%l]-s[(i+j)%l];
4     if(t==0) ++j; else (t<0?i:cho)+=j+1, j=0;
5     if(cho>=i) i=cho+1;
6 }

最小循环表示核心部分

原文地址:https://www.cnblogs.com/nealchen/p/12002895.html

时间: 2024-08-02 16:07:20

Lyndon分解和最小循环表示学习的相关文章

关于编程开发的最小系统学习法

文/向右奔跑(简书作者) 原文链接:http://www.jianshu.com/p/c340c2d3c152 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者". 今天中午与成长会shawn童靴见面,他在陆金所做Java开发,自学Python一年多了,能坚持下来很不容易.现在已经具备了一定的生产力. 不过,他说没有用py做过什么项目.我说,刚好有个想法,一个月前也试了试,不知道是不是感兴趣,用Java和py都可以做.最好是py,需要js熟悉一些. 我说,我想追踪一下现在成长

最小割学习小结

一直对最小割模型的理解不够深刻,这段时间学习.总结了一下. [强烈推荐胡伯涛和彭天翼的论文] 总结几点: (1)跑完一遍S-T最大流后,在最小割[S,T]中的边必定都是满流的边,但满流的边不一定都是最小割中的边. (2)最小割的任意方案:跑一遍S-T最大流,然后在残余网络中S能够达到的点为一个割集,剩下的点为另一个割集. (3)最小割方案的唯一性:跑一遍S-T最大流,如果在残余网络中任意一个点都能从S或者T出发达到,那么最小割方案有唯一性:否则没有唯一性. (4)跑一遍S-T最大流后,残余网络中

分治最小割 学习总结

这是一种可以较快的求解任意两点间最小割的算法 正常的暴力的话我们要枚举点对,一共要做O(n^2)次网络流 而我们注意到设某一个S->T最小割中两个点x,y,满足x在S集合且y在T集合中 设S->T的最小割为C,x->y的最小割为W 则一定有C>=W 若取得大于号,则x->y的最小割中一定有一个属于S集合点现在属于y集合或者一个属于T集合的点现在属于x集合 这样我们就可以分治处理并每次更新答案 实际上这样操作构成了一棵树,我们称之为最小割树,其任意两点的最小割等价于两点在树上路

全局最小割 学习总结

全局最小割的意思是在一个无向图中任取S和T,求最小割的最小值 还有一种描述是删掉无向图中的边使得其不连通的最小代价 当然,这种题目可以用分治+最小割来求解 但是时间复杂度大约在O(n^4)左右 有一种更好的求解方法可以在O(n^3)的时间复杂度内求解 做法是这样的: 首先对于图中任意两点S->T 要么S和T不在一个集合里时是答案,答案显然是S和T的最小割 否则S和T在一个集合里,我们可以将S和T缩成一个点,不难证明这样是等效的 我们模拟这个过程,每次任取S和T跑最小割,时间复杂度大概跟分治+最小

pyqt最小化学习

# -*- coding: cp936 -*- #!/usr/bin/env python # -*- coding:utf-8 -*- from PyQt4 import QtCore, QtGui class Window(QtGui.QMainWindow): def __init__(self): super(Window, self).__init__() self.setWindowTitle(u"托盘") icon = QtGui.QIcon("images/d

【一周读书】学习如何学习

书籍:<新知·学习的革命> 我同意叔本华所说的,把人们引向艺术和科学的最强烈的动机之一,是要逃避日常生活中令人厌恶的粗俗和使人绝望的沉闷,是要摆脱人们反复无常的欲望的桎梏.一个修养有素的人总是渴望逃避个人生活而进入客观知觉和思维的世界,这种愿望好比城市里的人渴望逃避喧嚣拥挤的环境,而到高山上去享受幽静的生活,在那里透过清寂而纯洁的空气,可以自由地眺望,陶醉于那似乎是为永恒而设计的宁静景色. ——爱因斯坦 新知是三联出版的一本杂志,这期的主题是「学习的革命」,我在kindle上看完了它.里面文章

Lyndon相关

Lyndon Words 定义 对于字符串 \(S\),若 \(S\) 的最小后缀为其本身,那么称 \(S\) 为 \(\text{Lyndon}\) 串(\(\text{Lyndon Words}\)) 即 \(S \in L\),\(\begin{cases} S是严格最小循环 \\ minsuf(s)=s \end{cases}\). 性质 \(Border(S)=\varnothing\) 推论 如果 \(u,v \in L, u \prec v\Rightarrow uv \in L\

bzoj2458: [BeiJing2011]最小三角形(分治+几何)

题目链接:bzoj2458: [BeiJing2011]最小三角形 学习推荐博客:分治法编程问题之最接近点对问题的算法分析 题解:先将所有点按x值排列,然后每次将当前区间[l,r]分成左右两半递归求解周长最小三角形.考虑到两半区间之间可能有连成最小三角形的情况,设dd为两半区间中最小三角形周长的最小值,筛选满足要求的点(x值与中点坐标x值的距离小于dd),然后按y值排序,进而暴搜出周长最小三角形. 1 #include<cstdio> 2 #include<cmath> 3 #in

Matlab中常见的神经网络训练函数和学习函数

一.训练函数 1.traingd Name:Gradient descent backpropagation (梯度下降反向传播算法 ) Description:triangd is a network training function that updates weight and bias values  according to gradient descent. 2.traingda Name:Gradient descent  with adaptive learning rate