ABC 416 G(字符串交换邻项贪心+DP)
G
首先考虑一个问题:给定 \(n\) 个字符串,输出将它们按照一定顺序首尾拼接后,字典序最大的字符串。
这是一道模板题:P1012
很容易往一个错误的方向去想:直接按照原字符串的字典序降序排序来拼接。错误的根本原因在于字符串的长度是参差不齐的。比如:5 和 526 两个数,若按照字典序降序来拼接,答案是 5265,而实际上,答案是 5526。
正确做法:对于任意两个字符串 \(a,b\),按照 \(a+b>b+a\) 的自定义排序方式对所有字符串排序,再拼接。
证明也很简单:将得到的字符串拆分成原字符串集合的若干段,考虑任意两个相邻段,均会满足上述的自定义偏序关系。否则便可能存在 \(a + b < b + a\) 的情况,此时交换 \(a, b\),答案必然更优。
再详细的证明可以看该题题解首页:tutorial
回到本题,考虑最后形成的字符串大概是什么样的形式(这里直接给出结论,证明见官解或其他博客吧,蒟蒻不太会证qwq):将所有字符串按照上述自定义排序后,答案一定是最小字符串形成的无限循环串的前缀。
既然答案形式已经固定,显然长度越短,字典序也越小。因此本题等价于求:用给定字符串集合中的恰好 \(k\) 个字符串(可重复),可以构成给定形式前缀的最短长度。
由于字符串集合中所有字符串的长度均 \(\leq 10\),而最劣情况下的答案是 \(k\) 个最小字符串构成的循环串,长度不超过 \(1e6\),因此可以考虑对模式串(上述的无限循环串)进行 \(dp\):
状态定义:\(dp_{i}\) 表示构成模式串\([1,i]\),需要给定字符串集合中的字符串的最大数量。
\(ans:\) \(dp[i] >= k\) 的最小的 \(i\),则答案为模式串\([1,i]\)
\(init: dp[0] = 0, dp[其他] = -inf\)
\(trans:\) 将字符串集合内的所有字符串均塞入一个 \(map\) 中,考虑到所有字符串长度最多为 \(10\),因此可以直接暴力枚举当前需要拼接的字符串的长度。若对应需要拼接的字符串存在,则直接从之前拼好的前缀转移过来即可:
复杂度 \(O(n*(max|S|)^{2}*log(max|S|))\),具体细节见代码。