Cod sursa(job #2266491)

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

using namespace std;

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

char a[NMAX + 5], aux[LENMAX + 5];

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(!('a' <= aux[i] && aux[i] <= 'z'))
        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 sol[101];

int main() {
    FILE *in, *out;
    in = fopen("ahocorasick.in", "r");
    out = fopen("ahocorasick.out", "w");

    fgets(a, NMAX + 3, in);
    int n;
    fscanf(in, "%d\n", &n);
    for(int i = 1; i <= n; i ++) {
        fgets(aux, LENMAX + 3, in);
        addTrie(root, 0, i);
    }
    buildLinks();

    cur = root;
    int asize = strlen(a);
    for(int i = 0; i < asize; 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 ++;
    }

    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 ++)
        fprintf(out, "%d\n", sol[i]);
    return 0;
}