deciphering - 解読 (Deciphering) Editorial by Mitsubachi


機密文書を示す文字列を $S$ とします。 $dp[i]$ を $S$ の先頭から $i$ 文字までの部分文字列から $1$ 個以上の文字を選んで得られる部分文字列で規則を満たすものの個数とします。ただし、問題文と同様に抜き出す位置が異なっても得られるものが同じなら区別せず、先頭から $i$ 文字目は必ず選ぶとします。
求めるべきものは $dp[1]+dp[2]+ \cdots + dp[L]$ です。

このDPを解くにあたり、同じ部分文字列を重複して数えないようにするにはどうすればよいでしょうか。部分文字列の各文字のindexが辞書順で最小となるようにするとよさそうです。

方針1 : 配るDP

便宜上 $dp[0]=1$ とします。 $dp[i]$ の寄与を考えましょう。 $dp[i]$ が管理している部分文字列に a を付ける場合、最も左にある a のindex $j$ を選べばよいです。よって、(規則に反しない限り) $dp[j] += dp[i]$ とすればよいです。これを b から z についても行えばよいです。
各文字のindexを管理することで、 $S$ の $i$ 文字目以降で最初に文字 $c$ が登場するindexは $O(L)$ で前準備することができるので、 文字の種類を $\sigma$ として $O(\sigma L)$ で解くことができました。

方針2 : 貰うDP

同様に \(dp[0]=1\) とします。 \(j < i\) かつ \(S\)\(j\) 文字目と \(i\) 文字目が同じような最大の \(j\) を考えます。ただし、そのような \(j\) が存在しない場合 \(j=0\) とします。このとき、 \(dp[i] = dp[j] + dp[j+1] + \cdots + dp[i-1]\) です。ただし、 \(S\)\(k \left( j \leq k \leq i-1 \right)\) 文字目の直後に \(i\) 文字目が来てはいけない場合、足す対象にはしません。
\(k < j\) について \(dp[i]\)\(dp[k]\) を足す場合、末尾 \(2\) 文字の元々あった場所は \(k,i\) となりますが \(k,j\) と選んだ方が辞書順で早いのでこれは矛盾です。
最後にこのDPの計算量を考えましょう。各文字について \(i-j\) の総和は \(O(L)\) となります。よって、 文字の種類を \(\sigma\) として \(O(\sigma L)\) で解くことができました。なお、累積和を用いて \(O(L)\) で解くこともできます。

posted:
last update: