Cod sursa(job #1772838)

Utilizator Eugen01Vasilescu Eugen Eugen01 Data 7 octombrie 2016 04:13:29
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.26 kb
#include <fstream>
#include <string>
#include <vector>
#include <iostream>

#define ALPHA_LEN 26

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

class Trie {
public:

    Trie* next[ALPHA_LEN];
    std::vector<int> indexes;
    Trie* fail;
    int nr;

    Trie() {
        for (int i = 0; i < ALPHA_LEN; i++)
            this->next[i] = NULL;
        nr = 0;
    }

    void insert(std::string &s, int pos, int index) {
        if (pos == s.size()) {
            this->indexes.push_back(index);
            return;
        }

        int i = s[pos] - 'a';
        if (this->next[i] == NULL) {
            this->next[i] = new Trie();
        }
        this->next[i]->insert(s, pos + 1, index);
    }
};

std::vector<Trie*> Q;

void BFS(Trie* root) {
    root->fail = root;
    Q.push_back(root);

    int index = 0;
    while (index < Q.size()) {
        Trie* node = Q[index];

        for (int i = 0; i < ALPHA_LEN; i++) {
            if (node->next[i] != NULL) {
                Trie* dolar = node->fail;
                while (dolar != root && dolar->next[i] == NULL)
                    dolar = dolar->fail;

                if (dolar->next[i] != NULL && dolar != node)
                    dolar = dolar->next[i];
                node->next[i]->fail = dolar;

                Q.push_back(node->next[i]);
            }
        }
        index++;
    }
    root->fail = NULL;
}

void anti_BFS(Trie *T, std::vector<int> &result) {
    for (int i = Q.size() - 1; i >= 0; i--) {
        Trie* node = Q[i];
        for (const auto &ind : node->indexes)
            result[ind] = node->nr;
        if (node->fail != NULL) {
            node->fail->nr += node->nr;
        }
    }
}

int main() {
    std::string text;
    in >> text;
    int n;
    in >> n;

    Trie *T = new Trie();
    for (int i = 0; i < n; i++) {
        std::string word;
        in >> word;
        T->insert(word, 0, i);
    }

    BFS(T);

    Trie *aux = T;
    for (int i = 0; i < text.size(); i++) {
        int pos = text[i] - 'a';
        while (aux != T && aux->next[pos] == NULL) aux = aux->fail;
        if (aux->next[pos] != NULL) aux = aux->next[pos];
        aux->nr++;
    }

    std::vector<int> result(n);
    anti_BFS(T, result);

    for (const auto &el : result) {
        out << el << "\n";
    }
}