概要
円環や循環シフトが絡む問題は、もととなる列を 2 つ繋げて考えることで見通しがよくなることがあります.
問題原案:achapi
解説
長さ 2N の数列 B を次のように定めます:
- B:=(A1,A2,…,AN,A1,A2,…,AN).
すると,この問題は次のように言い換えることができます:
- B の相異なる長さ N の連続部分列であって,辞書順で K 番目に小さいものを求めよ.
また,正整数 k(1≤k) に対して Sk,Tk を次のように定めます:
- Sk=(Bk,Bk+1,…,Bk+N)
- Tk=(Bk,Bk+1,…,B2N)
辞書順の定義を考えると,Si<Sj ならば Ti<Tj であるので,S が相異なるとすると,T のうち K 番目に小さいものを求める問題に帰着されます.
この問題は,たとえば Suffix Array を用いることで,Θ(NlogN) 時間などで解決できます.
また,Si=Sj(i=j) ならば Ti と Tj の最長共通接頭辞の長さは N 以上であるので,たとえば LCP Array を考えることで,Si=Sj なる i,j(i=j) を除外することができます.詳しくは実装例もご参照ください.
解説:uni_kakurenbo
実装例