Cod sursa(job #3231153)

Utilizator juniorOvidiu Rosca junior Data 25 mai 2024 08:39:42
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.86 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <queue>
#include <unordered_map>

using namespace std;

struct Nod {
    unordered_map<char, Nod*> copii;
    Nod* fail = nullptr;
    vector<int> terminari;
};

class AhoCorasick {
public:
    AhoCorasick(const vector<string>& cuvinte) {
        radacina = new Nod();
        for (int i = 0; i < cuvinte.size(); ++i)
            adaugaCuvant(cuvinte[i], i);
        construiesteFail();
    }

    void cauta(const string& text, vector<int>& rezultate) {
        Nod* nodCurent = radacina;
        for (int i = 0; i < text.size(); ++i) {
            while (nodCurent not_eq radacina and nodCurent->copii.find(text[i]) == nodCurent->copii.end())
                nodCurent = nodCurent->fail;
            if (nodCurent->copii.find(text[i]) not_eq nodCurent->copii.end())
                nodCurent = nodCurent->copii[text[i]];
            else
                nodCurent = radacina;
            
            for (int id : nodCurent->terminari)
                rezultate[id]++;
        }
    }

private:
    Nod* radacina;

    void adaugaCuvant(const string& cuvant, int id) {
        Nod* nodCurent = radacina;
        for (char c : cuvant) {
            if (nodCurent->copii.find(c) == nodCurent->copii.end())
                nodCurent->copii[c] = new Nod();
            nodCurent = nodCurent->copii[c];
        }
        nodCurent->terminari.push_back(id);
    }

    void construiesteFail() {
        queue<Nod*> q;
        for (auto& pereche : radacina->copii) {
            pereche.second->fail = radacina;
            q.push(pereche.second);
        }

        while (not q.empty()) {
            Nod* nodCurent = q.front();
            q.pop();

            for (auto& pereche : nodCurent->copii) {
                char c = pereche.first;
                Nod* copil = pereche.second;
                Nod* fail = nodCurent->fail;

                while (fail not_eq radacina and fail->copii.find(c) == fail->copii.end())
                    fail = fail->fail;

                if (fail->copii.find(c) not_eq fail->copii.end())
                    copil->fail = fail->copii[c];
                else
                    copil->fail = radacina;

                copil->terminari.insert(copil->terminari.end(), copil->fail->terminari.begin(), copil->fail->terminari.end());
                q.push(copil);
            }
        }
    }
};

int main() {
    ifstream fin("ahocorasick.in");
    ofstream fout("ahocorasick.out");

    string A;
    int n;
    fin >> A >> n;
    vector<string> cuvinte(n);
    for (int i = 0; i < n; ++i)
        fin >> cuvinte[i];

    AhoCorasick ac(cuvinte);
    vector<int> rezultate(n, 0);
    ac.cauta(A, rezultate);

    for (int i = 0; i < n; ++i)
        fout << rezultate[i] << '\n';

    return 0;
}