けんちょんの競プロ精進記録

競プロの精進記録や小ネタを書いていきます

AtCoder ABC 282 C - String Delimiter (灰色, 300 点)

フラグの考え方で解くのが一番分かりやすいと思った

問題概要

英小文字と、文字 ," からなる長さ  N の文字列  S が与えられます。

 S に含まれる文字 " の個数は偶数であることが保証されています。

 S に含まれる " の個数を  2K 個とすると、各  i=1,2,\dots,K について  2i−1 番目の " から  2i 番目の " までの文字のことを「括られた文字」と呼びます。

あなたの仕事は、文字列  S に含まれる , のうち、括られた文字でないもの を . で置き換えて得られる文字列を答えることです。

制約

  •  1 \le N \le 2 \times 10^{5}

考えたこと

色んな考え方がありそう。ここでは、for 文を用いて処理していく方法を考える。

for 文中の各文字に対して「今括られているのかどうか」を表すフラグ変数を用意する


is_inclusion ← 今括られているかどうかを表す値 (括られている:1、括られていない:0)


そして、次のような for 文で処理していけばよい。

int is_inclusion = 0;
for (int i = 0; i < N; ++i) {
    if (S[i] == '"') {
        // 括られているかどうかが変化する
        is_inclusion = 1 - is_inclusion  
    } else if (S[i] == ',' && !is_inclusion) {
        S[i] = '.';
    }
}

計算量は  O(N) となる。

コード

#include <bits/stdc++.h>
using namespace std;

int main() {
    int N;
    string S;
    cin >> N >> S;

    int is_inclusion = 0;
    for (int i = 0; i < N; ++i) {
        if (S[i] == '"') {
            // 括られているかどうかが変化する
            is_inclusion = 1 - is_inclusion;
        } else if (S[i] == ',' && !is_inclusion) {
            S[i] = '.';
        }
    }
    cout << S << endl;
}