Cod sursa(job #3124806)

Utilizator Vlad_NituNitu Vlad-Petru Vlad_Nitu Data 30 aprilie 2023 02:51:54
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.93 kb
// Source: https://drive.google.com/file/d/1puSAKcZT_Y3fz8MmYGOaa-QRJuyX1TB-gXO-Fl9dbE7L9sq2G-IAKKP8u0Fg/view
#include <bits/stdc++.h>

using namespace std;

const int ALPHABET_SIZE = 26;

struct Aho {
    Aho *children[ALPHABET_SIZE];
    Aho *failure;
    int cnt;

    Aho() {
        cnt = 0;
        failure = nullptr;
        for (int i = 0; i < ALPHABET_SIZE; ++i)
            children[i] = nullptr;
    }

    virtual ~Aho() {

    }
};

Aho *AHC = new Aho();

vector<Aho *> terminals;

// construct Trie <-> Keyword tree construction

// word_id - index of word in vector<string>& w
// pos - ch. position in w[word_id]
void insert(Aho *node, int pos, const int &word_id, const vector<string> &w) {
    if (pos == w[word_id].size()) {
        terminals.emplace_back(node);
        return;
    }

    const string &word = w[word_id];
    if (node->children[word[pos] - 'a'] == nullptr)
        node->children[word[pos] - 'a'] = new Aho();
    insert(node->children[word[pos] - 'a'], pos + 1, word_id, w);
}

void BFS() {

    AHC->failure = AHC;
    queue<Aho *> Q;

    // All nodes 's' of depth 1 have "failure link" back to root
    for (int i = 0; i < ALPHABET_SIZE; ++i)
        if (AHC->children[i]) {
            AHC->children[i]->failure = AHC;
            Q.push(AHC->children[i]);
        }

    while (!Q.empty()) {
        Aho *curr = Q.front();
        Q.pop();

        for (int i = 0; i < ALPHABET_SIZE; ++i)
            if (curr->children[i]) {
                Aho *fail = curr->failure;

                while (fail != AHC && fail->children[i] == nullptr)
                    fail = fail->failure;

                if (fail->children[i] && fail->children[i] != curr->children[i])
                    fail = fail->children[i];

                curr->children[i]->failure = fail;
                Q.push(curr->children[i]);
            }
    }

}

void scanText(const int &K, const string &text) {

    Aho *head = AHC;

    for (const auto& ch: text) {
        while (head != AHC && head->children[ch - 'a'] == nullptr)
            head = head->failure;
        if (head->children[ch - 'a'])
            head = head->children[ch - 'a'];

        head->cnt ++;
    }

    queue<Aho *> Q;
    stack<Aho *> st;
    Q.push(AHC);

    while (!Q.empty()) {
        Aho *curr = Q.front();
        Q.pop();

        st.push(curr);
        for (int i = 0; i < ALPHABET_SIZE; ++i)
            if (curr->children[i])
                Q.push(curr->children[i]);
    }

    while (!st.empty()){

        const Aho* node = st.top();
        st.pop();

        node->failure->cnt += node->cnt;
    }

    for (const Aho* node: terminals)
        cout << node->cnt << '\n';
}

string text;
int K;

int main() {

    freopen("ahocorasick.in", "r", stdin);
    freopen("ahocorasick.out", "w", stdout);

    cin >> text;
    cin >> K;
    vector<string> w(K);
    for (int i = 0; i < K; ++i) {
        cin >> w[i];
        insert(AHC, 0, i, w);
    }

    BFS();
    scanText(K, text);


    return 0;
}