Cod sursa(job #3242705)

Utilizator dey44andIoja Andrei-Iosif dey44and Data 13 septembrie 2024 17:59:44
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.17 kb
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

ifstream cin("ahocorasick.in");
ofstream cout("ahocorasick.out");

const int MAXN = 1000000 + 10;  // Maximum number of nodes in the trie
const int ALPHABET_SIZE = 26;   // For lowercase English letters

struct Node {
    int next[ALPHABET_SIZE];    // Children nodes
    int fail;                   // Failure link
    vector<int> outputs;        // Indices of patterns ending at this node

    Node() {
        memset(next, -1, sizeof(next));
        fail = 0;
    }
};

vector<Node> trie;
vector<int> counts;             // Counts of each pattern
vector<string> patterns;

void insert_pattern(const string& pattern, int index) {
    int node = 0;
    for (char ch : pattern) {
        int c = ch - 'a';
        if (trie[node].next[c] == -1) {
            trie[node].next[c] = trie.size();
            trie.emplace_back();
        }
        node = trie[node].next[c];
    }
    trie[node].outputs.push_back(index);
}

void build_failure_links() {
    queue<int> q;

    // Initialize failure links for immediate children of root
    for (int c = 0; c < ALPHABET_SIZE; ++c) {
        int child = trie[0].next[c];
        if (child != -1) {
            trie[child].fail = 0;
            q.push(child);
        } else {
            trie[0].next[c] = 0;  // Optimization to avoid checking for -1 during search
        }
    }

    // BFS to build failure links
    while (!q.empty()) {
        int rnode = q.front();
        q.pop();

        for (int c = 0; c < ALPHABET_SIZE; ++c) {
            int child = trie[rnode].next[c];
            if (child != -1) {
                int fnode = trie[rnode].fail;
                while (trie[fnode].next[c] == -1) {
                    fnode = trie[fnode].fail;
                }
                trie[child].fail = trie[fnode].next[c];
                trie[child].outputs.insert(trie[child].outputs.end(),
                                           trie[trie[child].fail].outputs.begin(),
                                           trie[trie[child].fail].outputs.end());
                q.push(child);
            }
        }
    }
}

void search_in_text(const string& text) {
    int node = 0;
    for (char ch : text) {
        int c = ch - 'a';
        while (trie[node].next[c] == -1) {
            node = trie[node].fail;
        }
        node = trie[node].next[c];
        for (int pattern_index : trie[node].outputs) {
            counts[pattern_index]++;
        }
    }
}

int main() {

    // Read the text
    string text;
    cin >> text;

    // Read the number of patterns
    int n;
    cin >> n;

    patterns.resize(n);
    counts.resize(n, 0);
    trie.emplace_back();  // Root node

    // Read and insert patterns into trie
    for (int i = 0; i < n; ++i) {
        cin >> patterns[i];
        insert_pattern(patterns[i], i);
    }

    // Build failure links
    build_failure_links();

    // Search patterns in text
    search_in_text(text);

    // Output the counts
    for (int i = 0; i < n; ++i) {
        cout << counts[i] << '\n';
    }

    return 0;
}