1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【競技プログラミング】AtCoder Beginner Contest 372_C問題

Posted at

問題

既存投稿一覧ページへのリンク

一覧ページ

Before

AtCoder Beginner Contest 371_E 問題

解法手順1

ステップ1:初期状態で "ABC" の個数をカウントする

まず、文字列 $ S $ の中に "ABC" という連続部分文字列がいくつあるかを数える。
これは、長さ $ N $ の文字列 $ S $ の各位置 $ i $(ただし $ 0 \leq i \leq N-3 $)について、
$ S[i], S[i+1], S[i+2] $ がそれぞれ 'A', 'B', 'C' ならカウントを1増やす。

abc_count = 0
for i in range(N - 2):
    if S[i] == "A" and S[i+1] == "B" and S[i+2] == "C":
        abc_count += 1

ステップ2:クエリごとに処理を繰り返す

各クエリでは、指定された位置の文字を変更し、そのたびに "ABC" の個数を更新して出力する。


2-1. 変更前の "ABC" を減算

変更する位置 $ X $ の前後で "ABC" が消える可能性があるので、$ X-2 $ から $ X $ までの3か所(ただし範囲外は除く)を調べ、もし "ABC" があればカウントを1減らす。

for k in range(3):
    pos = Xi - k
    if 0 <= pos and pos + 2 < N:
        if S[pos] == "A" and S[pos+1] == "B" and S[pos+2] == "C":
            abc_count -= 1

2-2. 文字列を更新

指定された位置の文字を新しい文字に置き換える。

S[Xi] = Ci

2-3. 変更後の "ABC" を加算

再び、$ X-2 $ から $ X $ までの3か所を調べ、今度は新しく "ABC" が現れた場所があればカウントを1増やす。

for k in range(3):
    pos = Xi - k
    if 0 <= pos and pos + 2 < N:
        if S[pos] == "A" and S[pos+1] == "B" and S[pos+2] == "C":
            abc_count += 1

2-4. 現在の "ABC" の個数を出力

print(abc_count)

まとめ:全体の流れ

base_image.create_20250420000806-ページ4.drawio.png

ACコード1

ac.py
import logging

def setup_logger(debug_mode):
    logger = logging.getLogger(__name__)
    if not logger.handlers:
        logger.setLevel(logging.DEBUG if debug_mode else logging.INFO)
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        file_handler = logging.FileHandler('program_trace.log', encoding="utf8")
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)
    logger.debug(f"ロガーのセットアップが完了しました。デバッグモード: {debug_mode}")
    return logger

def io_func():
    # 入力の受け取り
    N, Q = map(int, input().split())
    S = list(input())
    queries = []
    for _ in range(Q):
        Xi, Ci = input().split()
        queries.append((int(Xi) - 1, Ci))
    return N, Q, S, queries

def solve(N, Q, S, queries, logger):
    # 初期状態で"ABC"が何個あるかカウント
    abc_count = 0
    for i in range(N - 2):
        if S[i] == "A" and S[i+1] == "B" and S[i+2] == "C":
            abc_count += 1
    logger.debug(f"初期状態での'ABC'の個数: {abc_count}")

    for idx, (Xi, Ci) in enumerate(queries):
        logger.debug(f"クエリ{idx+1}: 位置={Xi+1}, 変更後文字='{Ci}'")
        # 変更前、影響範囲の"ABC"を減算
        for k in range(3):
            pos = Xi - k
            if 0 <= pos and pos + 2 < N:
                if S[pos] == "A" and S[pos+1] == "B" and S[pos+2] == "C":
                    abc_count -= 1
                    logger.debug(f"変更前: S[{pos}:{pos+3}]='{S[pos]}{S[pos+1]}{S[pos+2]}' -> 'ABC'減算 (新カウント: {abc_count})")
        # 文字列更新
        old_char = S[Xi]
        S[Xi] = Ci
        logger.debug(f"S[{Xi}]を'{old_char}'から'{Ci}'に変更")
        # 変更後、影響範囲の"ABC"を加算
        for k in range(3):
            pos = Xi - k
            if 0 <= pos and pos + 2 < N:
                if S[pos] == "A" and S[pos+1] == "B" and S[pos+2] == "C":
                    abc_count += 1
                    logger.debug(f"変更後: S[{pos}:{pos+3}]='{S[pos]}{S[pos+1]}{S[pos+2]}' -> 'ABC'加算 (新カウント: {abc_count})")
        print(abc_count)

def main():
    logger = setup_logger(debug_mode=True)
    N, Q, S, queries = io_func()
    solve(N, Q, S, queries, logger)

if __name__ == "__main__":
    main()

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?