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

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

AtCoder ABC 311 A - First ABC (灰色, 100 点)

フラグ変数を 3 個持ってもいいし、set 型を使ってもいい

問題概要

文字 'A', 'B', 'C' のみからなる、長さ  N の文字列  S が与えられます。

S を左から 1 文字ずつ見ていったときに、はじめて「A, B, C がすべて 1 回以上出現している」という条件を満たした状態になるのは、左から何文字目まで見たときですか?

制約

  •  3 \le N \le 100

解法 1:3 個のフラグを用いる

次の 3 個のフラグ変数を管理する方法が簡便だと思います。

  • exist_A:文字 A がここまでに出現したか (False / True)
  • exist_B:文字 B がここまでに出現したか (False / True)
  • exist_C:文字 C がここまでに出現したか (False / True)

for 文を用いて、文字列  S の各文字に応じて、これらの負グラフ変数の値を更新していきます。3 変数すべてが True になった瞬間に for 文を break して抜けます。

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

int main() {
    int N;
    string S;
    cin >> N >> S;
    
    // 3 個のフラグ変数 (最初はすべて false)
    bool exist_A = false, exist_B = false, exist_C = false;
    
    int i;  // はじめて A, B, C が揃う瞬間を捉える
    for (i = 0; i < N; ++i) {
        // 文字 S[i] に応じてフラグ変数を更新
        if (S[i] == 'A') exist_A = true;
        else if (S[i] == 'B') exist_B = true;
        else exist_C = true;
        
        // 3 変数すべてが true になった瞬間に for 文を抜ける
        if (exist_A && exist_B && exist_C) break;
    }
    
    // 抜けた瞬間の i を答える (i は 0 始まりなので、1 始まりにするために +1 する)
    cout << i+1 << endl;
}

解法 2:set 型を用いる

次に、「これまでに何種類の文字が登場したか」を管理するために、集合型変数 (set 型変数) を活用する方法もあります。

具体的な方法は下コードを参考にしてみてください。set 型の変数は、すでに含まれている文字を insert しても、重複は除外します。よって、set 型の変数のサイズ (要素数) が 3 になった瞬間に for 文を抜ければよいです。

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

int main() {
    int N;
    string S;
    cin >> N >> S;
    
    // set 型変数
    set<int> se;
    
    // se の要素数が 3 になる瞬間を捉える
    int i;
    for (i = 0; i < N; ++i) {
        se.insert(S[i]);
        
        if (se.size() == 3) break;
    }
    
    cout << i+1 << endl;
}