AGC037 A - Dividing a String
AGC037 A問題の解説と解答例です。問題文
解答例に載っているように、Nが最大になるような分割では、分割した文字列の長さはそれぞれ1か2のどちらかになる。 どの連続する2文字を連結して、分割するかをO(N)で求める必要があるため、動的計画法を用いて解く。 よってi文字目における最大分割数を上記の4パターンで記録しておく必要があるため、下記のようなリストを用意しておく。 このリストと上記の4パターンを対応させると次のようになる。 ここで、文字列Sの1文字目を1文字で分割する場合、文字列Sの1文字目と2文字目で2文字に分割する場合はそれぞれi文字目までの分割数が1なので、次のように初期化する。
(1文字目に対応するリストのインデックスは0) 最後にfor文で1文字目から文字列Sの最後の文字まで、上記の4パターンをリストに記録していく。問題の概要
解き方
入力された文字列Sのi文字目までの最大分割数を記録していく。分割された文字列は1文字か2文字であるため、想定されるパターンは次の4通り。
dp = [[0 for _ in range(4)] for _ in range(len(S))]
dp[0][0] = 1
dp[1][1] = 1
for i in range(1, len(S)):
# 直前は1文字で分割 次は1文字で分割
if S[i-1] != S[i]:
dp[i][0] = max(dp[i-1][0], dp[i-1][2]) + 1
# 直前は1文字で分割 次は2文字で分割
if i < len(S) - 1:
dp[i+1][1] = max(dp[i-1][0], dp[i-1][2]) + 1
# 直前は2文字で分割 次は1文字で分割
dp[i][2] = max(dp[i-1][1], dp[i-1][3]) + 1
# 直前は2文字で分割 次は2文字で分割
if 2 <= i < len(S)-1 and (S[i-2] != S[i] or S[i-1] != S[i+1]):
dp[i+1][3] = max(dp[i-1][1], dp[i-1][3]) + 1
解答コード全文
S = input()
dp = [[0 for _ in range(4)] for _ in range(len(S))]
dp[0][0] = 1
dp[1][1] = 1
for i in range(1, len(S)):
# 直前は1文字で分割 次は1文字で分割
if S[i-1] != S[i]:
dp[i][0] = max(dp[i-1][0], dp[i-1][2]) + 1
# 直前は1文字で分割 次は2文字で分割
if i < len(S) - 1:
dp[i+1][1] = max(dp[i-1][0], dp[i-1][2]) + 1
# 直前は2文字で分割 次は1文字で分割
dp[i][2] = max(dp[i-1][1], dp[i-1][3]) + 1
# 直前は2文字で分割 次は2文字で分割
if 2 <= i < len(S)-1 and (S[i-2] != S[i] or S[i-1] != S[i+1]):
dp[i+1][3] = max(dp[i-1][1], dp[i-1][3]) + 1
print(max(dp[-1]))