Cod sursa(job #3231155)

Utilizator juniorOvidiu Rosca junior Data 25 mai 2024 08:47:04
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.57 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;
};

void adaugaCuvant(Nod* radacina, 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(Nod* radacina) {
    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);
        }
    }
}

void cauta(Nod* radacina, 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]++;
    }
}

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];

    Nod* radacina = new Nod();
    for (int i = 0; i < cuvinte.size(); ++i)
        adaugaCuvant(radacina, cuvinte[i], i);

    construiesteFail(radacina);

    vector<int> rezultate(n, 0);
    cauta(radacina, A, rezultate);

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

    return 0;
}