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

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

JOI 予選 2008 B - JOIとIOI (AOJ 0522) (7Q, 難易度 2)

近年の ABC A 問題ではよくある「文字列の部分文字列を調べる」系の問題

問題概要

文字列  S が与えられる。この文字列に含まれる "JOI" の個数と、"IOI" の個数をそれぞれ求めよ。

制約

  •  1 \le |S| \le 10000

考えたこと

この問題よりも易しいバージョンとして、「文字列  S 中に含まれる文字 j の個数を求めよ」が考えられる。この問題は、次のような for 文で解ける。

int res = 0;
for (int i = 0; i < S.size(); i++) {
    if (S[i] == 'j') res++;
}

今回は、 S に含まれるかを判定するものが「単一の文字」ではなく、「3 文字の文字列」である点が難しい。

しかし、実は、やるべきことはほとんど変わらない。文字列  S i 文字目から数えて 3 文字分を取り出した文字列は、C++ では

S.substr(i, 3)

によって取得できる。これが "JOI" や "IOI" に一致するかどうかを調べていけばよい!

コード

for 文のループ変数  i の範囲について考える。

「文字列  S i 文字目から数えて 3 文字分」の末尾の文字は、 S i + 2 文字目であることに注意しよう。よって、下のコードでは、for 文の終端条件を i + 2 < S.size() とした。

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

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

    int joi = 0, ioi = 0;
    for (int i = 0; i + 2 < S.size(); i++) {
        if (S.substr(i, 3) == "JOI") joi++;
        if (S.substr(i, 3) == "IOI") ioi++;
    }
    cout << joi << endl;
    cout << ioi << endl;
}