H - K-th Shifted Array

2 secs 1024 MB
uni_kakurenbo's icon uni_kakurenbo

概要

円環や循環シフトが絡む問題は、もととなる列を 22 つ繋げて考えることで見通しがよくなることがあります.

問題原案:achapi

解説

長さ 2N2N の数列 BB を次のように定めます:

  • B(A1,A2,,AN,A1,A2,,AN)B \coloneqq (A_1, A_2, \ldots, A_N, A_1, A_2, \ldots, A_N)

すると,この問題は次のように言い換えることができます:

  • BB の相異なる長さ NN の連続部分列であって,辞書順で KK 番目に小さいものを求めよ.

また,正整数 k  (1k)k \; \scriptsize (1 \leq k) に対して Sk,TkS_k, T_k を次のように定めます:

  • Sk=(Bk,Bk+1,,Bk+N)S_k = (B_k, B_{k+1}, \ldots, B_{k+N})
  • Tk=(Bk,Bk+1,,B2N)T_k = (B_k, B_{k+1}, \ldots, B_{2N})

辞書順の定義を考えると,Si<SjS_i < S_j ならば Ti<TjT_i < T_j であるので,SS が相異なるとすると,TT のうち KK 番目に小さいものを求める問題に帰着されます.

この問題は,たとえば Suffix Array を用いることで,Θ(NlogN)\Theta(N \log N) 時間などで解決できます.

また,Si=Sj(ij)S_i = S_j \scriptsize \; (i \not= j) ならば TiT_iTjT_j の最長共通接頭辞の長さは NN 以上であるので,たとえば LCP Array を考えることで,Si=SjS_i = S_j なる i,j(ij)i, j \scriptsize \; (i \not= j) を除外することができます.詳しくは実装例もご参照ください.

解説:uni_kakurenbo

実装例

C++