Cod sursa(job #2427571)

Utilizator PrekzursilAndrei Visalon Prekzursil Data 1 iunie 2019 00:00:38
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.1 kb
#include <vector>
#include <fstream>
#include <cstring>
struct nod_trie {
    int nr_in;
    std::vector<int> list_edge;
    nod_trie *next_chr[31], *link_fail;
    nod_trie () {
        link_fail = NULL;
        nr_in = 0;
        std::memset(next_chr, 0, sizeof next_chr);
    }
};
template <typename the_type> class automat_aho_coarasick {
private:
    the_type *root;
    int nr_words = 0;
    std::vector<the_type*> sign_at;
public:
    automat_aho_coarasick () {
        root = new nod_trie();
        nr_words = 0;
    }
    void recursive_deiteration(the_type *this_node) {
        for (unsigned int i = 0; i < 31; ++i) {
            if (this_node -> next_chr[i])
                recursive_deiteration(this_node -> next_chr[i]);
        }
        delete this_node;
        return;
    }
    ~automat_aho_coarasick() {
        recursive_deiteration(root);
    }
    int get_idx (char c) {
        int idx_next = 0;
        if ('a' <= c && c <= 'z')
            idx_next = c - 'a';
        else {
            if (c == ':')
                idx_next = 'z' - 'a' + 1;
            if (c == '\\')
                idx_next = 'z' - 'a' + 2;
            if (c == '.')
                idx_next = 'z' - 'a' + 3;
            if (c == '_')
                idx_next = 'z' - 'a' + 4;
        }
        return idx_next;
    }
    void add_in_trie (const std::string &word) {
        the_type *next_nod = root;
        int idx_next;
        for (unsigned int i = 0; i < word.length(); ++i) {
            idx_next = get_idx(word[i]);
            if (next_nod->next_chr[idx_next] == 0)
                next_nod->next_chr[idx_next] = new nod_trie();
            next_nod = next_nod->next_chr[idx_next];
        }
        ++nr_words;
        next_nod->list_edge.push_back(nr_words);
    }
    void build_automat () {
        root -> link_fail = root;
        sign_at.clear();
        sign_at.push_back(root);
        for (unsigned int i = 0; i < sign_at.size(); ++i) {
            for (unsigned int j = 0; j < 31; ++j) {
                if (sign_at[i]->next_chr[j] != 0) {
                    sign_at.push_back(sign_at[i]->next_chr[j]);
                    the_type *from = sign_at[i]->link_fail;
                    while (from != root && from->next_chr[j] == 0)
                        from = from->link_fail;
                    if (sign_at[i] != root && from->next_chr[j] != 0)
                        sign_at[i]->next_chr[j]->link_fail = from->next_chr[j];
                    else
                        sign_at[i]->next_chr[j]->link_fail = root;
                }
            }
        }
    }
    std::vector<int> check_string(std::string str) {
        the_type *check_nod = root;
        int idx_next;
        std::vector<int> nr_found;
        nr_found.resize(nr_words + 1);
        for (unsigned int i = 0; i < str.length(); ++i) {
            idx_next = get_idx(str[i]);
            while (check_nod->next_chr[idx_next] == 0 &&
                check_nod != root)
                check_nod = check_nod->link_fail;
            if (check_nod->next_chr[idx_next])
                check_nod = check_nod->next_chr[idx_next];
            ++check_nod->nr_in;
        }
        int bound = sign_at.size() - 1;
        for (unsigned int i = bound; i > 0; --i) {
            check_nod = sign_at[i];
            check_nod->link_fail->nr_in += check_nod->nr_in;
            int cnt = check_nod->list_edge.size();
            for (int j = 0; j < cnt; ++j)
                nr_found[check_nod->list_edge[j]] = check_nod->nr_in;
        }
        return nr_found;
    }
};
int main() {
    std::ifstream fin("ahocorasick.in");
    std::ofstream fout("ahocorasick.out");
    std::string sir;
    int n;
    automat_aho_coarasick<nod_trie> solver;
    std::string cuvinte;
    std::vector<int> sol;
    fin >> sir;
    fin >> n;
    for (int i = 0; i < n; ++i) {
        fin >> cuvinte;
        solver.add_in_trie(cuvinte);
    }
    solver.build_automat();
    sol = solver.check_string(sir);
    for (int i = 1; i < sol.size(); ++i) {
        fout << sol[i] << "\n";
    }
    return 0;
}