ABC225F
题面
link
有\(n\)个字符串,从中选出\(m\)个以任意顺序拼起来,求所有情况中字典序最小的。
题解
首先考虑如果已经选出了\(m\)个字符串,我们应该按什么顺序拼起来。
算是一个trick,重载小于号为\(S_1+S_2<S_2+S_1\)。(如果交换两个相邻的可以更优的话肯定交换)
但是这个排序方式符合要求吗,会不会出现\(S_1<S_2,S_2<S_3\)但\(S_3<S_1\)的情况呢。
其实不会,你可以将长度相等的两个字符串的字典序比较想象成两个26进制的数比较大小,所以:
\[\begin{aligned}
&S_1+S_2<S_2+S_1\\
\Leftrightarrow&S_1\times26^{|S_2|}+S_2<S_2\times26^{|S_1|}+S_1\\
\Leftrightarrow&\dfrac{S_1}{26^{|S_1|}-1}<\dfrac{S_2}{26^{|S_2|}-1}
\end{aligned}
\]
最后你会发现其实排序依照的只有\(S_i\)自己的信息,并没有必须得两个字符串才会有意义。
所以按这个方法给字符串排序之后,就可以进行DP看究竟选哪\(m\)个。
方法有很多,但错误方法更多。大致原因都是因为字符串没有局部最优得整体最优,即如果\(S_1\)是\(S_2\)的前缀,则\(S_1<S_2\)的,但可能出现\(S_1+x>S_2+x\)的情况,所以正确DP的核心就是去除这种前缀关系。
-
方法一:从后往前DP,这样就保证了不会出现前缀的情况,而后缀情况因为后面不会再接新字符串了,所以可以保证最优。转移:
\[f[i][j]=min(f[i+1][j],S_i+f[i+1][j-1]) \] -
方法二:将长度引入状态,在相同长度下,字典序最小一定更优,也去除了前缀带来的影响。
启发
- 给多个字符串拼接最小字典序的排序方法。
- 处理字符串字典序最小/最大的问题时,注意前缀的情况,以及通过反向DP去除影响。