B - Two Languages 解説 by MMNMM

より高速な解法

公式解説では、アルファベットサイズ \(\sigma\) に対して時間計算量 \(\displaystyle O\!\left(\sigma\sum _ {i=1} ^ Q|w _ i|\right)\) のアルゴリズムを解説しました。 この解説では、アルファベットサイズ \(\sigma\) がワードサイズの定数倍以下であることを仮定して時間計算量 \(\displaystyle O\!\left(\sigma+\sum _ {i=1} ^ Q|w _ i|\right)\) となるアルゴリズムについて話します。

高橋語で使われるが青木語では使われない文字の集合を \(C _ {\mathrm{takahashi}}\) 、青木語で使われるが高橋語では使われない文字の集合を \(C _ {\mathrm{aoki}}\) とします。 この \(2\) つの集合には共通部分がないことに注意してください。 \(C _ {\mathrm{takahashi}}\) に含まれている文字が \(w _ i\) に含まれているとき、かつそのときに限り \(w _ i\) は高橋語の単語であることが確定します。青木語についても同様です。

文字に \(0,1,\ldots,\sigma-1\) の番号 \(\operatorname{ord}\) をつけ、文字の集合 \(C\) を \(\sigma\) bit の整数 \(\displaystyle\mathrm{mask} _ C=\sum _ {c\in C}2 ^ {\operatorname{ord}( c)}\) で管理することを考えます。 すると、\(2\) つの文字の集合 \(C _ 1,C _ 2\) に共通部分があるかどうかは \(\mathrm{mask} _ {C _ 1}\) と \(\mathrm{mask} _ {C _ 2}\) のビットごとの論理積が \(0\) でないかで判定することができます。

実装例は以下のようになります。

#include <iostream>
#include <string>
#include <numeric>

int main() {
    using namespace std;
    unsigned N, M;
    string S, T;
    cin >> N >> M >> S >> T;

    // 高橋語で使われる文字の集合
    const unsigned S_mask = transform_reduce(begin(S), end(S), 0U, bit_or{}, [](const char c){return 1U << (c - 'a');});
    // 青木語で使われる文字の集合
    const unsigned T_mask = transform_reduce(begin(T), end(T), 0U, bit_or{}, [](const char c){return 1U << (c - 'a');});

    // 高橋語でしか使われない文字の集合
    const unsigned only_takahashi = S_mask & ~T_mask;
    // 青木語でしか使われない文字の集合
    const unsigned only_aoki = ~S_mask & T_mask;

    unsigned Q;
    cin >> Q;
    for (unsigned i{}; i < Q; ++i) {
        string w;
        cin >> w;
        const unsigned w_mask = transform_reduce(begin(w), end(w), 0U, bit_or{}, [](const char c){return 1U << (c - 'a');});

        if (w_mask & only_takahashi) // 高橋語でしか使われない文字があれば
            cout << "Takahashi" << endl; // 高橋語
        else if (w_mask & only_aoki) // 青木語でしか使われない文字があれば
            cout << "Aoki" << endl; // 青木語
        else // どちらでもなければ
            cout << "Unknown" << endl; // 確定しない
    }
    return 0;
}

投稿日時:
最終更新: