Cod sursa(job #3232835)

Utilizator Mircea_DonciuDonciu Mircea Mircea_Donciu Data 1 iunie 2024 17:40:14
Problema Aho-Corasick Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.95 kb
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>

using namespace std;

struct TrieNode {
    unordered_map<char, TrieNode*> children;
    TrieNode* fail;
    vector<int> output;
};

class AhoCorasick {
public:
    AhoCorasick(const vector<string>& patterns) {
        root = new TrieNode();
        buildTrie(patterns);
        buildFailureLinks();
    }

    vector<int> search(const string& text) {
        vector<int> result(patterns.size(), 0);
        TrieNode* current = root;
        for (char c : text) {
            while (current != root && current->children.find(c) == current->children.end()) {
                current = current->fail;
            }
            if (current->children.find(c) != current->children.end()) {
                current = current->children[c];
            }
            for (int patternIndex : current->output) {
                result[patternIndex]++;
            }
        }
        return result;
    }

private:
    TrieNode* root;
    vector<string> patterns;

    void buildTrie(const vector<string>& patterns) {
        this->patterns = patterns;
        for (int i = 0; i < patterns.size(); i++) {
            const string& pattern = patterns[i];
            TrieNode* current = root;
            for (char c : pattern) {
                if (current->children.find(c) == current->children.end()) {
                    current->children[c] = new TrieNode();
                }
                current = current->children[c];
            }
            current->output.push_back(i);
        }
    }

    void buildFailureLinks() {
        queue<TrieNode*> q;
        for (auto& [c, child] : root->children) {
            child->fail = root;
            q.push(child);
        }
        while (!q.empty()) {
            TrieNode* current = q.front();
            q.pop();
            for (auto& [c, child] : current->children) {
                TrieNode* fail = current->fail;
                while (fail != root && fail->children.find(c) == fail->children.end()) {
                    fail = fail->fail;
                }
                if (fail->children.find(c) != fail->children.end()) {
                    child->fail = fail->children[c];
                } else {
                    child->fail = root;
                }
                child->output.insert(child->output.end(), child->fail->output.begin(), child->fail->output.end());
                q.push(child);
            }
        }
    }
};

int main() {
    // Read input
    string A;
    cin >> A;
    int n;
    cin >> n;
    vector<string> patterns(n);
    for (int i = 0; i < n; ++i) {
        cin >> patterns[i];
    }

    // Initialize Aho-Corasick
    AhoCorasick ac(patterns);

    // Search patterns in text A
    vector<int> result = ac.search(A);

    // Output results
    for (int count : result) {
        cout << count << endl;
    }

    return 0;
}