Cod sursa(job #796654)

Utilizator AndreyPAndrei Poenaru AndreyP Data 12 octombrie 2012 00:50:09
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.82 kb
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

#define MAX_LEN_A 1000010
#define MAX_LEN_WORD 10010
#define MAX_N 110
#define CHARSET_LEN 26

struct ACNode {
    ACNode()
        : matchCount(0)
        , fallback(NULL)
    {
        memset(children, 0, sizeof(children));
    }

    ~ACNode() {
        for (int i = 0; i < CHARSET_LEN; ++i) {
            if (children[i]) {
                delete children[i];
            }
        }
    }

    void insert(char *c, int wordIndex) {
        if (*c == '\0') {
            words.push_back(wordIndex);
            return;
        }

        int childIndex = int(*c - 'a');
        if (!children[childIndex]) {
            children[childIndex] = new ACNode;
        }

        children[childIndex]->insert(c + 1, wordIndex);
    }

    vector< int > words;
    ACNode* children[CHARSET_LEN];
    int matchCount;
    ACNode* fallback;
};

char A[MAX_LEN_A];
int N;
ACNode root;
int nq;
ACNode* q[MAX_N * MAX_LEN_WORD];
int res[MAX_N];

void buildACTrie() {
    char w[MAX_LEN_WORD];

    scanf("%d\n", &N);
    for (int i = 0; i < N; ++i) {
        scanf("%s", w);
        root.insert(w, i);
    }

    nq = 0;
    q[0] = &root;
    root.fallback = &root;
    int ind = 0;
    ACNode* now;
    ACNode* pi;
    ACNode* next;
    while (ind <= nq) {
        now = q[ind];
        ++ind;

        for (int i = 0; i < CHARSET_LEN; ++i) {
            next = now->children[i];
            if (!next) {
                continue;
            }

            if (now == &root) {
                next->fallback = &root;
                q[++nq] = next;
                continue;
            }

            for (pi = now->fallback; pi != &root && !pi->children[i]; pi = pi->fallback) {
                ;
            }

            if (pi->children[i]) {
                pi = pi->children[i];
            }
            next->fallback = pi;

            q[++nq] = next;
        }
    }
}

void processA() {
    ACNode* pi = &root;
    for (int i = 0; A[i] != '\0'; ++i) {
        while (pi != &root && !pi->children[int(A[i] - 'a')]) {
            pi = pi->fallback;
        }

        if (pi->children[int(A[i] - 'a')]) {
            pi = pi->children[int(A[i] - 'a')];
        }

        ++(pi->matchCount);
    }
}

void computeResult() {
    ACNode* now;
    for (int ind = nq; ind >=0; --ind) {
        now = q[ind];

        for (size_t i = 0, lim = now->words.size(); i < lim; ++i) {
            res[now->words[i]] += now->matchCount;
        }

        now->fallback->matchCount += now->matchCount;
    }
}

void printResult() {
    for (int i = 0; i < N; ++i) {
        printf("%d\n", res[i]);
    }
}

int main() {
    freopen("ahocorasick.in", "r", stdin);
    freopen("ahocorasick.out", "w", stdout);

    scanf("%s", A);
    buildACTrie();
    processA();
    computeResult();
    printResult();

    return 0;
}