Cod sursa(job #2266469)

Utilizator caesar2001Stoica Alexandru caesar2001 Data 22 octombrie 2018 18:17:16
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.35 kb
#include <bits/stdc++.h>

using namespace std;
ifstream in("ahocorasick.in");
ofstream out("ahocorasick.out");

const int SIGMA = 26;
const int NMAX = 1000000;

string a, aux;

struct Trie {
    int cnt;
    Trie* link;
    Trie* son[SIGMA];
    vector<int> words;

    Trie() {
        words.clear();
        link = NULL;
        cnt = 0;
        memset(son, NULL, sizeof son);
    }

};

Trie* root = new Trie();
Trie* cur;

void addTrie(Trie* node, int i, int ind) {
    if(i == aux.size())
        node -> words.push_back(ind);
    else {
        if(node -> son[aux[i] - 'a'] == NULL)
            node -> son[aux[i] - 'a'] = new Trie();
        addTrie(node -> son[aux[i] - 'a'], i + 1, ind);
    }
}

Trie* nodelist[NMAX];
int sz;
void buildLinks() {
    queue<Trie*> q;
    for(int i = 0; i < SIGMA; i ++)
        if(root -> son[i] != NULL) {
            root -> son[i] -> link = root;
            q.push(root -> son[i]);
        }

    while(q.size()) {
        Trie* node = q.front();
        q.pop();
        nodelist[sz ++] = node;

        for(int i = 0; i < SIGMA; i ++) {
            if(node -> son[i] != NULL) {
                Trie* pretender = node;
                do {
                    pretender = pretender -> link;
                } while(pretender != root && (pretender -> son[i] == NULL));
                if(pretender -> son[i] != NULL)
                    pretender = pretender -> son[i];
                node -> son[i] -> link = pretender;
                q.push(node -> son[i]);
            }
        }
    }
}

int main() {
    in >> a;
    int n;
    in >> n;
    for(int i = 1; i <= n; i ++) {
        aux.clear();
        in >> aux;
        addTrie(root, 0, i);
    }
    buildLinks();

    cur = root;
    for(int i = 0; i < a.size(); i ++) {
        while(cur != root && (cur -> son[a[i] - 'a'] == NULL))
            cur = cur -> link;
        if(cur -> son[a[i] - 'a'] != NULL)
            cur = cur -> son[a[i] - 'a'];
        cur -> cnt ++;
    }

    vector<int> sol(n + 1, 0);
    for(int i = sz - 1; i >= 0; i --) {
        Trie* node = nodelist[i];
        node -> link -> cnt += node -> cnt;
        for(auto it : node -> words) {
            sol[it] += node -> cnt;
        }
    }
    for(int i = 1; i <= n; i ++)
        out << sol[i] << "\n";
    return 0;
}