Do geese see god?
Description
给一个字符串 $s$ 和一个整数 $k$ 。求所有最短的满足 $s$ 是他的一个子序列并且是一个回文串的字符串中字典序第 $k$ 大的。
Solution
令 $f[i][j]$ 表示 $s$ 中 $i$ 到 $j$ 所构成的字符串至少还要再添加几个字符使得其变成回文串。
令 $g[i][j]$ 表示满足最短的条件的前提下的添加字符的方案数。
这两个数组都可以通过简单的 $O(n^2)$ 的 dp 完成。
接下来便是求第 $k$ 大的字符串。如果 $k > g[1][n]$ 直接输出无解。接下来处理有解的情况。
用 solve(l, r, k)
表示从 $s_l$ 到 $s_r$ 构成的字符串满足添加字符最少的前提下所构成的字典序第 $k$ 大的回文串。
$l=r$ 时,直接返回 $s_l$
$s_l = s_r$ 时,返回
s[l] + solve(l + 1, r - 1, k) + s[r]
(这里加法 = 按顺序拼接 = string 加法)$s_l \not= s_r$ 时,我们有两种方法
- 把字符串变成
s[l] + solve(l + 1, r) + s[l]
即在后面添加一个 $s_l$ 并且把中间变成回文 - 把字符串变成
s[r] + solve(l, r - 1) + s[r]
即在前面添加一个 $s_r$ 并且把中间变成回文
此时,我们显然会贪心的走字典序小的那一边,这取决于 $s_l$ 和 $s_r$ 的大小。
不妨设 $s_l < s_r$ 那么如果 $g[l+1][r] >= k$ 我们就直接往第一种情况递归。否则把 $k$ 减掉 $g[l+1][r]$ 放到第二种情况递归。对于 $s_l > s_r$ 也是同理。
- 把字符串变成
Code
1 |
|