Cod sursa(job #2266419)

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

using namespace std;

const int SIGMA = 30;
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;
        for(int i = 0; i < SIGMA; i ++)
            son[i] = NULL;
    }

};

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

inline bool ischar(char c) {
    if('a' <= c && c <= 'z')
        return 1;
    return 0;
}

void addTrie(Trie* node, int i, int ind) {
    if(!ischar(aux[i]))
        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);
    }
}

vector<Trie*> nodelist;
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.push_back(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() {
    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 ++) {
        for(int j = 0; j < LENMAX + 3; j ++)
            aux[j] = '\n';
        fgets(aux, LENMAX + 3, in);
        addTrie(root, 0, i);
    }
    buildLinks();

    cur = root;
    int i = 0;
    while(ischar(a[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 ++;
        i ++;
    }

    vector<int> sol(n + 1, 0);
    for(int i = nodelist.size() - 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;
}