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

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

AtCoder ABC 236 C - Route Map (5Q, 灰色, 300 点)

set の練習問題!

問題概要

 N 個の文字列  S_{1}, S_{2}, \dots, S_{N} と、 M 個の文字列  T_{1}, T_{2}, \dots, T_{N} が与えられる。

 i = 1, 2, \dots, N について、 T_{1}, T_{2}, \dots, T_{M} の中に  S_{i} と一致するものがあるかどうかを判定せよ。

制約

  •  2 \le M \le N \le 10^{5}
  • 各文字列の長さは 10 以下

考えたこと

set 型のよい練習問題。

 T_{1}, T_{2}, \dots, T_{M} を格納する集合(C++ であれば set<string> 型)を用意しよう。

そして、 i = 1, 2, \dots, N について、 S_{i} が集合に含まれるかどうかを判定していけばよい。

計算量

C++ の set 型を用いた場合、文字列の最大長さを  A として、計算量は

  • 集合を作る部分: M 回挿入するので、計算量は  O(A M \log M)
  • 判定していく部分: N 回判定するので、計算量は  O(A N \log M)

よって、全体の計算量は  O(A (N + M) \log M) と評価できる。

コード

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

int main() {
    int N, M;
    cin >> N >> M;
    vector<string> S(N), T(M);
    for (int i = 0; i < N; i++) cin >> S[i];

    set<string> se;
    for (int i = 0; i < M; i++) {
        cin >> T[i];
        se.insert(T[i]);
    }

    for (int i = 0; i < N; i++) {
        if (se.count(S[i])) cout << "Yes" << endl;
        else cout << "No" << endl;
    }
}