Cod sursa(job #3297967)

Utilizator urweakurweak urweak Data 24 mai 2025 23:12:20
Problema Aho-Corasick Scor 15
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.27 kb
#include <iostream>
#include <fstream>
#include <queue>
#include <vector>
#include <algorithm>
#include <map> 

using namespace std;

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

const int ALPHABET_SIZE = 26;

struct Node {
    int next[ALPHABET_SIZE];     // next character edges
    int fail;                    // failure link
    vector<int> output;          // pattern indices ending at this node

    Node() {
        fill(next, next + ALPHABET_SIZE, -1);
        fail = 0;
    }
};

class AhoCorasick {
private:
    vector<Node> trie;
    vector<string> patterns;

public:
    AhoCorasick() {
        trie.emplace_back();  // root node
    }

    void addPattern(const string& pattern) {
        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].output.push_back(patterns.size());
        patterns.push_back(pattern);
    }

    void build() {
        queue<int> q;
        for (int c = 0; c < ALPHABET_SIZE; ++c) {
            int child = trie[0].next[c];
            if (child != -1) {
                trie[child].fail = 0;
                q.push(child);
            }
        }

        while (!q.empty()) {
            int current = q.front(); q.pop();
            for (int c = 0; c < ALPHABET_SIZE; ++c) {
                int child = trie[current].next[c];
                if (child == -1) continue;

                int f = trie[current].fail;
                while (f && trie[f].next[c] == -1)
                    f = trie[f].fail;
                
                if (trie[f].next[c] != -1)
                    f = trie[f].next[c];
                
                trie[child].fail = f;

                // Merge output
                trie[child].output.insert(
                    trie[child].output.end(),
                    trie[f].output.begin(),
                    trie[f].output.end()
                );

                q.push(child);
            }
        }
    }

    vector<pair<int, string>> search(const string& text) {
        vector<pair<int, string>> result;
        int node = 0;

        for (int i = 0; i < text.size(); ++i) {
            int c = text[i] - 'a';
            while (node && trie[node].next[c] == -1)
                node = trie[node].fail;

            if (trie[node].next[c] != -1)
                node = trie[node].next[c];

            for (int index : trie[node].output) {
                result.emplace_back(i - patterns[index].size() + 1, patterns[index]);
            }
        }

        return result;
    }
};

int main() {
    map<string, int> res;
    AhoCorasick ac;
    string text; 
    int num;
    in >> text;
    in >> num;
    for(int i = 0; i<num; i++)
    {
        string patt;
        in >> patt;
        ac.addPattern(patt);
        res[patt] = 0;
    }

    ac.build();

    auto matches = ac.search(text);
    
    for (auto& match : matches) {
        // cout << "Found pattern \"" << match.second
        //      << "\" at index " << match.first << "\n";
        res[match.second]++;    
    }

    for(auto it : res)
    {
        auto [key, value] = it;
        out << value << "\n";
    }    

    return 0;
}