Cod sursa(job #1922668)

Utilizator hevelebalazshevele balazs hevelebalazs Data 10 martie 2017 18:21:33
Problema Aho-Corasick Scor 0
Compilator c Status done
Runda Arhiva educationala Marime 2.53 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;
    struct Trie *sufend;

    char end;
    char c;

    int id;
} Trie;

Trie root;

void put(char *str, int id) {
    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->child[v]->id = id;
            trie->child[v]->c = str[i];
        }
        trie = trie->child[v];
    }

    trie->end = 1;
}

Trie *Q[1000000];
int qn;

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

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

        if (trie != &root) {
            int val = chval(trie->c);

            trie->suffix = &root;
            Trie *suffix = trie->parent->suffix;

            while (suffix) {
                if (suffix->child[val]) {
                    trie->suffix = suffix->child[val];
                    break;
                }
                suffix = suffix->suffix;
            }

            if (trie->suffix->end) trie->sufend = trie->suffix;
            else trie->sufend = trie->suffix->sufend;
        }

        int j;
        for (j = 0; j < 26; ++j) {
            if (trie->child[j]) Q[qn++] = trie->child[j];
        }
    }
}

int C[100];
void countall(Trie *trie) {
    if (trie->end) C[trie->id]++;

    Trie *sufend = trie->sufend;
    while (sufend) {
        C[sufend->id]++;
        sufend = sufend->sufend;
    }
}

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];

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);
        put(B, i);
    }

    calcsuf();

    Trie *state = &root;

    for (i = 0; A[i]; ++i) {
        state = go(state, A[i]);

        countall(state);
    }

    for (i = 0; i < n; ++i) printf("%i\n", C[i]);

    return 0;
}