ARC058-F 文字列大好きいろはちゃん

 

 

atcoder.jp

公式解説とは違うやり方れふ.

K\le 10^4O(K^2)は余裕っ(素振り)

解法

dp[i]:i文字の, 辞書順最小の文字列を作るとして, 最後に使う文字列のインデックス(複数ある場合, 最小のもの)

これを順に求め, 最後に復元しまふ.

 

dp[i]からの遷移としてvalidなものは, 次の条件を満たすものれふ.

  1. 使う文字列のインデックスがdp[i]より大きい
  2. その遷移をした結果, 長さKの文字列が作れなくなるということが無い
  3. 他のvalidな遷移に対応する文字列と比較して, その遷移によって生成される文字列が辞書順で大きくなってしまわない

2に違反する遷移は, あらかじめ部分和DPをしておけば検出できまふ.

3に違反する例を挙げまふ.

N=4, K=4, S = \{"abcd", "ab", "d", "d"\}

この時, dp[2] =1となりまふが, そこからdp[3]=2などとする遷移はinvalidれふ.

("abcd"に対して"abd"は辞書順で大きいため)

このような遷移を弾くには, この例における"abcd"のように, 辞書順最小の可能性のある文字列のうち最も先まで文字を確定させている文字列を記憶し, 比較する必要がありまふ.

 

また, 次のようなケースがありまふ.

N=4, K=4, S = \{"abcd", "ab", "a", "d"\}

このようなケースでは, dp[3]=2を求めた瞬間に, dp[0]から求めたdp[4]=0がinvalidになりまふ. 辞書順最小の可能性のある文字列のうち最も先まで文字を確定させている文字列が"abcd"から"aba"に更新され, それ以前に求めた遷移が正しいと限らなくなった形れふ. このようなケースは, dp[i]を求めた直後にdp[i+1]以降をO(K)かけて潰せば良いれふ.

 

以上の解法を実現するためには, 文字列ab文字目以降と文字列cd文字目以降に対し, 先頭から何文字共通しているかや, 辞書順でどちらが小さいかを高速に求める必要がありまふ. これらは, Suffix Array, およびそのLCPを求めてやればO(1)で達成できまふ.

参考

niuez.hatenablog.com

提出コード

atcoder.jp

終わりに

金diffれふが, 時間をいくらでもかけてよければ通しやすいタイプ……?