Official
F - Inserting Process Editorial
by
F - Inserting Process Editorial
by
toam
操作を逆から見て,\(T\) から一文字ずつ削除していくことで 空文字列にする方法を数えることにします.
残った文字の位置を集合で持つことにします.今残っている位置が \(S=\lbrace S_1,S_2,\ldots,S_k\rbrace\ (1\leq S_1\lt S_2\lt \ldots\lt S_k\leq N)\) だったとします.文字列から文字を削除することは,ある \(i\) を選んで \(S\) から \(S_i\) を削除することに対応します.
ただし,削除した結果同じ文字列になってしまうことがあります.例えば,\(T\) が abcade で \(S=\lbrace 1, 4, 6\rbrace\) のとき,\(S\) から \(1\) を削除しても \(4\) を削除しても残った文字列は ae となってしまいます.この重複を避けるためには,例えば以下のように制限すればよいです.
- \(i\geq 2\) かつ \(T_{S_{i-1}}=T_{S_{i}}\) のとき,\(S\) から \(S_i\) (右側)を削除していけない.(すなわち,同じ文字が連続して残っている区間では左から順に削除する.)
このような遷移の制限のもと,bit DP でこの問題を解くことができます.計算量は \(O(N2^N)\) です.
mod = 998244353
n = int(input())
t = input()
dp = [0] * (1 << n)
dp[(1 << n) - 1] = 1
for bit in range((1 << n) - 1, -1, -1):
dp[bit] %= mod
pre = "?"
for i in range(n):
if (bit >> i) & 1:
if pre != t[i]:
dp[bit ^ (1 << i)] += dp[bit]
pre = t[i]
print(dp[0])
posted:
last update:
