Abstract
- ABC 122 D問題(400点) 「We like AGC」 を解きました。
- python
こんな人にオススメ
problem
- 以下の条件を満たす文字列を AGC文字列 とする。
- A,G,C,T の4文字でできている
- "AGC"という文字列を含まない
- 任意の文字において、隣の文字と入れ替える操作をしても、"AGC"という部分文字列を作れない
- 整数N(>=3)が与えられた時に、長さNの AGC文字列 が何通りあるかもとめよ。(10**9+7でMODをとる)
atcoder.jp
constraints
input
output
Idea
- 長さNの文字列を全通り作って試すと、4**N個の文字列ができる。これは、多すぎてN=100の時に大変なことになる。
- 文字列が違反するかどうかは、途中に特定のパターンを含むかどうかで、判定できる。(GAC,ACG,A?GC,AG?C)
solution
- 長さ iの AGC文字列 は何通りできるかを、i=3からi=Nまで計算していく
- 動的計画法
point
- 一文字増やす際に、違反させないように増やす。
- 正規表現を使って、違反のパターンを シンプルに記述
- MODするのを忘れない。
solution
import re
import sys
sys.setrecursionlimit(10**9)
input = sys.stdin.readline
MOD = 10**9+7
N = int(input())
CHAR = ["A", "C", "G", "T"]
invalid_pattern = r'ACG|GAC|A.?GC|AG.?C'
invalid_reg = re.compile(invalid_pattern)
dp = {a+b+c: 1 if not invalid_reg.search(a+b+c)
else 0 for a in CHAR for b in CHAR for c in CHAR}
for i in range(N-3):
next_dp = {key: 0 for key, _ in dp.items()}
for key, val in dp.items():
for c in CHAR:
next_val = key+c
if invalid_reg.search(next_val):
continue
else:
next_dp[(key+c)[1:]] += dp[key]
dp = next_dp
for key in dp.keys():
dp[key] %= MOD
print(sum(dp.values()) % MOD)
最後に
- 解説pdfでは、メモ化佐伯の解法が書いてあって、そっちでもできる。
- 数え上げのDP苦手なので、難易度400点以上に思えたけど、しっかり練習していきたい。