码迷,mamicode.com
首页 > 其他好文 > 详细

[CF594E]Cutting the Line

时间:2019-12-07 18:05:26      阅读:537      评论:0      收藏:0      [点我收藏+]

标签:部分   i+1   min   连续   比较大小   之一   算法   strong   大小   

字符串神题。

要点:Lyndon分解,扩展KMP, 最小循环表示,贪心。

题目链接

题意

已知字符串 $S$, 请你把它切成不超过 $k$ 段,并翻转其中若干段,使得最终字符串的字典序最小。

题解

先想一想如果 $k=|S|$ 怎么做。此时我们发现可以去掉“是否翻转”的决策,因为如果有一段不翻转,我们就把它拆成若干个单字符分别翻转。

我们的策略是:

策略1. 每次切出反串字典序最小的后缀对应的原串前缀翻转,然后去掉这个前缀接着做。

证明:如果2019年内没补上就是鸽了。

在这种情况下,我们可以对反串 $S^r$ 作Lyndon分解,不难发现Lyndon分解实际上就是这个过程。

然后想一想原问题,我们发现两个事实:

  1. 如果连续若干个翻转的字符串都是单字符串,它们合起来只要占据一段。
  2. 如果连续若干个翻转的字符串都相等,它们合起来也只要占据一段。

这样可以尽量地节省步数。当 $k\ge3$ 时,策略1改进后也成立:

策略1改. 每次切出反串Lyndon分解中的最后极长的「相等段」或者「单字符段」对应的原串前缀翻转,然后去掉这个前缀接着做。

证明:如果2019年内没补上就是鸽了。

于是,现不妨假设 $k \le 2$.

如果 $S^r$ 已经是 Lyndon 串,那么显然答案就是 $S^r$; 如果 $k=1$, 那么显然答案就是 $\min\{S, S^r\}$.

现在,字符串将被我们分为前后两部分,并按照这两部分是否翻转分为三大类操作,或者不操作直接留下 $S$.

(一)前一部分翻转,后一部分不翻转,设为 $S^r[L:]S[-L:]$.

设 $S^r$ 的Lyndon分解合并相等段后为 $S^r[:d_1], S^r[d_1:d_2], \ldots, S^r[d_{n-1}:d_n]$, 其中 $d_n=|S|$, 那么我们有结论:

性质1. 存在整数 $q \in [1, n]$ 使得 $L=d_q$ 为本情况的最优解之一。

性质2. 如果设 $p$ 为最大的小于 $n$ 的正整数,满足 $S^r[d_p:]$ 不为 $S^r[d_{p+1}:]$ 的前缀,特别地,若不存在如此的正整数则设 $p=0$, 则 $q>p$.

性质3. $\forall p<i<n,$ $d_{i+1}-d_i \le |S|-d_i$. 这表明枚举查找 $p$ 的时间为 $O(|S|)$.

性质4. 当 $p<m \le n$ 时,S^r[d_m:]S[-d_m:]$ 是单峰函数。

以上四条性质的证明:如果2019年内没补上就是鸽了。

因此只需要枚举找到最大的整数 $q$ 使得 $q=p+1$ 或 $S^r[d_q:]S[-d_q:]<S^r[d_{q-1}:]S[-d_{q-1}:]$, 后者等价于 $S[-d_{q-1}:-d_q]<S^r[d_{q-1}-d_q+|S|:]$, 因此直接比较的总时间也是 $O(|S|)$.

(二)前一部分不翻转,后一部分翻转,设为 $S[:L]S^r[:-L]$.

设 $i<j$, 比较 $S[:i]S^r[:-i]$ 与 $S[:j]S^r[:-j]$ 实际上相当于比较 $S^r[:-i]=S^r[:j-i]S^r[j-i:-i]$ 与 $S^r[i:j]S^r[:-j]$, 于是可以考虑用扩展 $KMP$ 算法求这两个串的最长公共前缀以比较大小。

(三)两部分都翻转,即 $S^r$ 的循环表示。求最小循环表示即可。

综上所述,本题可以在 $O(|S|)$ 时空内解决。

不知道有没有漏洞的实现链接

[CF594E]Cutting the Line

标签:部分   i+1   min   连续   比较大小   之一   算法   strong   大小   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!