英小文字からなる長さ N の文字列を S とします。まず、そもそも S に "abcd" が含まれている(条件A)なら明らかに良い文字列です。そうでないなら、「整数 1≤k≤3 が存在して、 S の末尾 k 文字が "abcd" の先頭 k 文字、そして S の先頭 4−k 文字が "abcd" の末尾 4−k 文字であること」(条件B)が必要十分です。
"abcd" が含まれている長さ N の文字列(すなわち、条件Aを満たすものの個数)が AN 通りあるとします。このとき、条件Bを満たす長さ N の文字列は、末尾-先頭をつなぐ "abcd" でない長さ N−4 の部分で "abcd" を連続部分列として含まなければよいです。これは 3×(26N−4−AN−4) 通りです。
よって、答えを SN とすると
SN=AN+3×(26N−4−AN−4)
通りであることが分かります。一般の n に対して An を数えればよく、これにはいろいろな方法があります。
DP の方法
いわゆる耳DPと言われる手法でこれを解きます。 dp[i][j] を、長さ i の文字列であって、状態が j であるものの個数とします。ただし、状態は以下のように定めます。
- 状態 1:文字列の末尾は "a" である
- 状態 2:文字列の末尾は "ab" である
- 状態 3:文字列の末尾は "abc" である
- 状態 4:いままでに文字列の末尾が "abcd" になったことがある
- 状態 0:状態 1 ~状態 4 のいずれでもない
状態 4 の末尾に何を追加しても状態 4 のままです。状態 1 のとき、末尾に "a" を追加したら状態 1 に、"b" を追加したら状態 2 に、それ以外の文字を追加したら状態 0 に遷移します。
状態 0,2,3 も同様に考えることができ、DP ができます。よって、 "abcd" の文字列長を K=4 として O(NK) で解くことができました。(ただし "abcd" の部分が一般の文字列 t だった場合、さらに工夫が必要です。)
包除原理
「i から i+3 文字目が "abcd" となっている」という条件で包除原理を適用します. 条件が c1,c2,⋯,ck の位置で満たされているとして, その位置にある "abcd" を "@" の 1 文字と見なすことにします. 例えば c2,c7 で条件が満たされているとして, "babcdeabcdfaaaabcddd" は "b@e@faaa@dd" に変換されます. 変換後も "abcd" が含まれている場合がありますが, 無視することにします.
c2,c7 に "abcd" が入るという条件下で, 残りの N−8 文字は自由に決められます. よって, この条件を満たす長さ N (N は十分大きい) の文字列の個数は 26N−8 通りあることになります. ここで, "abcd" の位置の制約を外し, 個数が K 個, という場合, "@" の位置の決め方は (KN−4K+K) 通りあり, 残りの文字の決め方は 26N−4K 通りあります. 以上から, 包除原理より
AN=K=1∑⌊N/4⌋(−1)K−1(KN−3K)26N−4K
母関数を用いる方法
"abcd" を含まない長さ N の文字列の個数を CN とします.
F(x)=C0+C1x+C2x2+⋯
とおきます. 一方, 長さ N の文字列の個数を DN=26N として
G(x)=D0+D1x+D2x2+⋯=1−26x1
とおきます. 長さ N の文字列の構造は「(長さ0以上の"abcd"を含まない文字列) ("abcd") (長さ0以上の"abcd"を含まない文字列) … (長さ0以上の"abcd"を含まない文字列) ("abcd") (長さ0以上の"abcd"を含まない文字列) 」となるので,
G(x)=F(x)+F(x)x4F(x)+F(x)x4F(x)x4F(x)+⋯=1−x4F(x)F(x)
となります. G(x)=1/(1−26x) より, 変形すると
F(x)=1−26x+x41
を得ます. よって
CN=26CN−1−CN−4
を得ます. AN=26N−CN なので求まりました.