Official

F - Substring of Sorted String Editorial by kyopro_friends


\(S\)\(L\) 文字目から \(R\) 文字目までからなる部分文字列を \(S[L:R]\) と表すことにします。

文字列 \(S[L:R]\) が、\(S\) を昇順に並び替えた文字列 \(T\) の部分文字列であるための必要十分条件は、次の \(2\) 条件をともに満たすことです。

  • \(S[L:R]\) は文字の昇順に並んでいる
  • \(S[L:R]\) に含まれる最小の文字を \(c\)、最大の文字を \(d\) としたとき、\(c\) より大きく\(d\) より小さいすべての文字が、\(S[L:R]\)\(S\) に同じ個数含まれている

これは、\(S\) の区間が各文字を含む個数がわかれば確かめることができます。したがって、文字ごとに、ある区間にその文字が何個登場するかを表すセグメントツリーを用いることで、文字の種類数を \(\sigma\) として \(O(\sigma(N+Q\log N))\) で問題を解くことができます。

Writer解(C++)

追記:
\(S[L:R]\) が文字の昇順に並んでいるかは、次のようにして \(O(\sigma \log N)\) で求めることができます。

  • \(S[L:R]\) に各文字が何度登場するか求め、\(C_a,C_b,\ldots\) とする。
  • \(S[L:L+C_a]\)a\(C_a\) 個あることを確かめる
  • \(S[L+C_a:L+C_a+C_b]\)b\(C_b\) 個あることを確かめる
  • \(\ldots\)

posted:
last update: