「CTSC2016」香山的树 (KMP+dp)
「CTSC2016」香山的树 (KMP+dp)
题目大意
对于所有的串,满足:
- 其是本身的最小循环同构。
- 其最小循环同构位置唯一。
给定一个这样的串,求其字典序在所有合法串中的 \(\text{rank}\),以及求 \(\text{rank}=k\) 的串。
简要分析
这是一个暴力的做法,有一定优化空间。
约定 \(\Sigma\) 为字符集。
显然是要枚举答案,求出当前字符串在所有答案中的 \(\text{rank}\) ,不断增大答案 \(S\) 的字典序。
求出字典序 \(>S\) 的个数,考虑 \(\text{dp}\) 求解。
比较大小可以想到要不断进行前缀匹配,因此考虑 \(\text{kmp}\)。
因为要 \(\text{dp}\) 的是一个循环同构串,不妨直接扩展为无限循环的串,\(\text{dp}\) 一个 最小 的循环节。
不妨先考虑没有字典序限制的简单情形,也就是抛开 \(\text{kmp}\) 判断字典序,计算长度为 \(i\) 的方案数。
对于限制条件 2 ,等价于不存在循环分解,可以对于长度进行有关倍数的容斥,即 \(g_i=f_i-\sum_{d|i,d<i} g_d\)。
对于限制条件 \(1\),不妨枚举一个无限循环串 \(S\) 的最优匹配位置为 \(st\),然后 \(\text{dp}\) 一个长度为 \(i\) 的循环节。
显然要满足的条件是:
\(\text{dp}\) 了 \(i\) 个字符之后匹配状态为 \(st\)。
在 \(\text{dp}\) 过程中如果 \(\text{kmp}\) 出现失配,必须满足当前字符更大。
注意这里的边界情况,当匹配位置恰好等于 \(|S|\) 时,可能会将恰好为 \(S\) 的情况算入,因此要特判。
中途不能匹配到比 \(st\) 更大的位置。
同样的会出现两种重复计算:
串内出现了循环,即上文提到的容斥。
多个不同的开始位置都合法。
由于不存在循环,即每一个循环同构的位置都不同,考虑直接记录匹配过程中恰好为 \(st\) 的次数,在最终方案里除掉。
由以上思路,定义 \(f_{i,j,d}\) 表示当前 \(\text{dp}\) 了 \(i\) 位,匹配状态为 \(j\),中途出现了 \(d\) 个恰好为 \(st\) 的匹配位置。
在求解完所有 \(f_{i,j,d}\) 后,先对于长度倍数进行容斥,由于多了一个维度,容斥时实际上变成了 \(f_{i,j,d}-f_{i,jk,dk}\) 的形式。随后再除以 \(d\) 算进答案。
可以得到一个 \(O(n^3|\Sigma|)\) 的暴力 dp,算上枚举起始位置,复杂度为 \(O(n^4|\Sigma|)\)。
由于还需要按位二分答案,所以复杂度为 \(O(n^5|\Sigma|\log |\Sigma|)\),实际可以通过。
一个小优化:每次二分时,只有 \(st=|S|\) 或者 \(st=|S|-1\) 的部分需要重新 \(dp\) (即 \(st<|S|-1\) 时 \(S\) 的变化与 \(\text{dp}\) 值无关)。
因此实际复杂度为 \(O(n^4|\Sigma|\log |\Sigma|)\)。
1 |
|