Cod sursa(job #1922768)

Utilizator hevelebalazshevele balazs hevelebalazs Data 10 martie 2017 18:49:22
Problema Aho-Corasick Scor 100
Compilator c Status done
Runda Arhiva educationala Marime 2.11 kb
#include <stdio.h>
#include <stdlib.h>

int chval(char c) {
    return c - 'a';
}

char ch(int i) {
    return (char)(i + 'a');
}

typedef struct Trie {
    struct Trie *parent;
    struct Trie *child[26];

    struct Trie *suffix;

    int id;
    int count;
} Trie;

Trie root;

Trie *put(char *str) {
    Trie *trie = &root;

    int i;
    for (i = 0; str[i]; ++i) {
        int v = chval(str[i]);

        if (!trie->child[v]) {
            trie->child[v] = calloc(1, sizeof(Trie));
            trie->child[v]->parent = trie;
        }
        trie = trie->child[v];
    }

    return trie;
}

Trie *Q[1000000];
int qn;

void calcsuf() {
    qn = 0;
    Q[qn++] = &root;

    int i;
    for (i = 0; i < qn; ++i) {
        Trie *trie = Q[i];

        int j;
        for (j = 0; j < 26; ++j) {
            Trie *child = trie->child[j];
            if (!child) continue;

            Trie *suffix = trie->suffix;
            while (suffix && !suffix->child[j]) suffix = suffix->suffix;

            if (suffix) child->suffix = suffix->child[j];
            else child->suffix = &root;

            Q[qn++] = child;
        }
    }
}

Trie *go(Trie *state, char c) {
    int v = chval(c);

    if (state->child[v]) return state->child[v];

    Trie *suffix = state->suffix;
    while (suffix) {
        if (suffix->child[v]) return suffix->child[v];
        suffix = suffix->suffix;
    }

    return &root;
}

char A[1000001];
char B[10001];
Trie *T[100];

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

    scanf("%s", A);

    int i, n;
    scanf("%i", &n);

    for (i = 0; i < n; ++i) {
        scanf("%s", B);
        T[i] = put(B);
    }

    calcsuf();

    Trie *state = &root;

    for (i = 0; A[i]; ++i) {
        state = go(state, A[i]);
        ++state->count;
    }

    for (i = qn - 1; i >= 1; --i) {
        Trie *trie = Q[i];
        if (trie->suffix) trie->suffix->count += trie->count;
    }

    for (i = 0; i < n; ++i) printf("%i\n", T[i]->count);

    return 0;
}