C - No Streak 解説
by
Nyaan
説明のために文字列の問題に言い換えて説明します。すなわち次の通りです。
A,B,Xからなる文字列 \(S\) であって次の条件を満たすものの個数は?
Aは \(a\) 個、Bは \(b\) 個,Xは \(x\) 個含まれる。AAとBBは共に部分文字列として含まれない。- \(S\) の任意の prefix T について (\(T\) に含まれる
Aの個数) \(\geq\) (\(T\) に含まれるBの個数) が成り立つ。
カタラン数の要領で数え上げを行います。ここで通常のカタラン数の求め方のうちの 1 つを振り返ると、対角線をまたいだタイミングで A, B を反転させるという発想で (\((a, b)\) へ行く通り数) - (\((b-1, a+1)\) へ行く通り数) = \(\binom{a+b}{a} - \binom{a+b}{b-1}\) という式を導出できるのでした。これを応用します。
今回の問題はカタラン数の数え上げに「AA, BB が現れない」という条件を追加したものです。カタラン数の数え上げ同様、対角線をまたいだ後の A, B を反転させた文字列を数えて全体から引くという方針で数えることにします。
A, B が隣接しないという条件は対角線をまたいだ後の A, B を反転させてもだいたい成立します。ただし、対角線をまたいだ直後については、BB, BX は許されて BA は許されないという点に注意が要ります。よって、ラフに説明すると
- (\((a,b,x)\) に行く通り数) から
- (\((b-1,a+1,x)\) に行く通り数, ただし対角線をまたいだ直後が
BB) と - (\((b-1,a+1,x)\) に行く通り数, ただし対角線をまたいだ直後が
BX) を引いたもの
が答えになるということです。
A, B, X がそれぞれ \(a\) 個, \(b\) 個, \(x\) 個あり、これらを AA, BBが部分文字列として含まれないように並べる通り数を \(f(a, b, x)\) と置きます。すると先の 3 つは \(f(a,b,x)\) を用いて表現できることが以下のように確認できます。
- \(f(a,b,x)\) 通り
BBをBと置き換えた列と対応させられるので \(f(b-1,a,x)\) 通りBXの次の文字がBか(A|X)かで場合分け (BXの次の文字が存在しないことはあり得ない)BXBの場合 :BXBをBに置き換えた列と対応させられるので \(f(b-1,a,x-1)\) 通りBX(A|X)の場合 :BXをBに置き換えた列と対応させられるので \(f(b-1,a+1,x-1)\) 通り
よって、\(f(a, b, x)\) が線形時間で数えられればこの問題を十分高速に解くことが出来ます。
\(f(a, b, x)\) の計算方法を説明します。\(a = 0\) の場合はコーナー処理することにして、\(a \gt 0\) とします。文字列の A と X の並びだけを考えたときに A が隣接する箇所が \(k\) 箇所 \((0 \leq k \leq a-1)\) あるとします。すると、
- 隣接する箇所の選び方が \(\binom{a-1}{k}\) 通り
Xを入れてよい隙間は \((a-1) - k + 2 = a - k + 1\) 箇所あり、そのうち \(a-k-1\) 箇所はXを \(1\) 個以上入れる必要がある。よってXの置き方は \(\binom{x - (a - k - 1) + (a-k)}{(a-k)} = \binom{x + 1}{a - k}\) 通りBを入れてよい隙間は \(a + x + 1\) 箇所あり、そのうち \(k\) 箇所はBを入れる必要がある隙間である。よって \(\binom{a+x+1-k}{b-k}\) 通り
となりこれらの積で表すことが出来るため、線形時間で計算できます。
以上の方法によりこの問題を \(\mathrm{O}(N)\) 程度で計算することが出来て、これは十分高速です。
投稿日時:
最終更新:
