G - 辞書順 Editorial by Kiri8128
\(N = |s|\) とし、アルファベットの数を \(M\) とします。 \(i\) 文字目以降に初めてアルファベット \(x\) が出てくる位置を \({\rm next}_{i, x}\) とします。 これは後ろからDPすれば求まります。
「異なる位置であっても文字列として同じであれば区別しない」という条件は、「文字列として同じものは、選ぶ位置が辞書順で最小となるもののみ選ぶ(※)」と言い換えられます。
各 \(i\) について、 \(i\) 文字目以降で作れる文字列の個数 \(X[i]\) が分かっていれば、答えを前から順番に試すことで \(O(NM)\) で求められます。 例えば、 \(x\) で始まる部分列は \(X[{\rm next}_{i, x}]\) なので、 \(x\) を “a”、 “b” と順番に見て合計がいつ \(K\) を超えるかを調べることで答えの \(1\) 文字目が分かります。 \(2\) 文字目以降も同様です。
あとは \(X[i]\) を求められれば良いですが、これも後ろからのDPで求められます。(※)に注意すると次の式が成立します。
\(X[i] = X[i+1] * 2 - X[{\rm next}_{i}]\)
なおこのままやると \(X[i]\) が大きくなり過ぎてしまいますが、本問では \(K\) 以下しか使わないので適当に floor して良いです。 以上により本問は \(O(NM)\) で解くことができました。
この提出では \({\rm next}_{i, x}\) を愚直に \(N\times M\) 配列で持つと MLE したので、 \({\rm next}_{i}={\rm next}_{i, s(i)}\) のみ配列で持って、後は逐次更新しています。
posted:
last update: