Cod sursa(job #1965805)

Utilizator andreigasparoviciAndrei Gasparovici andreigasparovici Data 14 aprilie 2017 17:02:10
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.02 kb
#include <bits/stdc++.h>
using namespace std;

const int MAXN  = 1000005;

char word[MAXN];
int n;
struct trie_node
{
    int nr;
    trie_node *copii[26];
    trie_node *fail;
    vector<trie_node* >out;

    trie_node() {
        nr = 0;
        for(int i = 0; i < 26; i++){
            copii[i] = 0;
        }
        fail = 0;
        out.clear();
    }

}*root = new trie_node;

trie_node *fr[MAXN];

queue<trie_node* >coada;

trie_node* trie_insert(trie_node *&node, char *p)
{
    if(!*p)
        return node;

    if(!node->copii[*p - 'a'])
        node->copii[*p - 'a'] = new trie_node;

    return trie_insert(node->copii[*p - 'a'], p + 1);
}

void parcurg(trie_node *t) {
    for(int i = 0;i < t->out.size(); i++){
        parcurg(t->out[i]);
        t->nr += t->out[i]->nr;
    }
}

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

    ios_base::sync_with_stdio(false);

    in>>word>>n;

    for(int i = 1; i <= n; i++){
        char s[100000];
        in>>s;
        fr[i] = trie_insert(root, s);
    }

    coada.push(root);

    while(!coada.empty()) {
        trie_node *nod = coada.front();
        coada.pop();
        for(int i = 0; i < 26; i++){

            if(!nod->copii[i])
                continue;

            trie_node *f = nod->fail;
            while(f && !f->copii[i]){
                f = f->fail;
            }

            if(!f){
                nod->copii[i]->fail = root;
                root->out.push_back(nod->copii[i]);
            } else {
                nod->copii[i]->fail = f->copii[i];
                f->copii[i]->out.push_back(nod->copii[i]);
            }

            coada.push(nod->copii[i]);
        }
    }

    trie_node *t = root;

    for(char *p = word; *p; p++){
        int ch = *p - 'a';
        while(t && !t->copii[ch]){
            t = t->fail; 
        }

        if(!t)
            t = root;
        else
            t = t->copii[ch];

        t->nr++;
    }

    parcurg(root);

    for(int i = 1; i <= n; i++)
        out<<fr[i]->nr<<'\n';
    
    return 0;
}