1 条题解
-
0
String and Operations 题解
思路
把字符连同它最初的位置编号一起看待,操作顺序就固定为编号 。
小规模可以保存“当前排列中的每个原编号及其字符”,依次枚举 0、U、D、L、R 五种操作并对相同状态去重,最后在所有字符序列中取字典序最小者。
为了处理更大规模,需要观察已经处理的前缀与尚未处理部分的边界。令 是处理完最初的前 个字符后,所有与后续操作有关的边界形态中字典序最小的长度 字符串。字符 单独进行 0、U、D 中的一种时能够达到的最小字符记为
交换只能越过当前边界附近的一个字符。分类讨论最后一次涉及边界的交换,可以证明 只可能由以下四个候选取最小值得到。以下下标从 开始, 表示 的前 个字符。
- 不跨边界交换:。
- 当前字符向左交换:。
- 前一个边界字符向右交换:$\operatorname{pre}(F_i,i-1)+s_i+\operatorname{last}(F_i)$。
- 连续涉及前两个边界字符:$\operatorname{pre}(F_{i-1},i-2)+s_i+\operatorname{last}(F_{i-1})+s_{i-1}$。
不存在第五种边界次序:一个原编号在自己的操作结束后不会再次主动交换,而尚未操作的编号又只能由紧邻边界的已处理字符带动。因此更远位置的影响已经包含在 或 中。对同一边界形态保留字典序最小的前缀不会损失最优解,因为后续拼接和局部交换只会读取其末尾并保留更早的公共前缀。
直接存储字符串并构造、比较这四个候选需要 时间,足以通过第二子任务。
满分算法把字符串表示为规范化持久化线段树。每个叶子是一个字符;内部结点由左右儿子的编号唯一决定,并通过二元组查表合并。于是两个相同子串必然具有同一结点编号,不依赖随机哈希,也不存在碰撞。
上述每个候选相对某个旧版本只修改至多三个位置,所以用持久化点修改即可构造。比较两个候选时,若左儿子编号不同就递归左侧,否则递归右侧,能在 时间内定位第一个不同字符。每一步只有常数个候选。
做法
对每个测试用例建立覆盖 个位置的二叉树,未使用位置填入统一哨兵字符。叶子字符和内部左右儿子对都做规范化编号。
从空版本 开始,按顺序枚举 。根据上面的四类边界形态,从 或 出发做一至三次持久化点修改;用规范树的首次不同位置比较选出最小根,保存为 。最后逐点读取 的前 个字符。
独立复核程序直接保存普通字符串并使用同一完整分类;小规模复核程序则按原操作定义枚举带编号的排列状态。
复杂度
状态枚举算法的时间复杂度上界为 ,空间复杂度为 。
普通字符串动态规划对每个测试用例的时间复杂度为 ,空间复杂度为 。
规范化持久化线段树算法对每个测试用例的期望时间复杂度为 ,空间复杂度为 ;期望仅来自内部结点二元组字典的常数时间查找,字符串相等与字典序比较本身是精确的。
- 1
信息
- ID
- 1259
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 0
- 上传者