Cod sursa(job #1922591)

Utilizator hevelebalazshevele balazs hevelebalazs Data 10 martie 2017 17:59:26
Problema Aho-Corasick Scor 25
Compilator c Status done
Runda Arhiva educationala Marime 2.65 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;

    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 = trie->child[v];
    }

    trie->end = 1;
}

void calcsuf(Trie *trie, char c) {
    if (!trie) return;

    trie->suffix = 0;

    if (c) {
        trie->suffix = &root;

        int val = chval(c);

        Trie *parent = trie->parent;
        while (parent) {
            if (parent->child[val]) {
                Trie *child = parent->child[val];

                if (child != trie) {
                    trie->suffix = child;
                    break;
                }
            }
            parent = parent->suffix;
        }
    }

    int i;
    for (i = 0; i < 26; ++i) {
        if (trie->child[i]) calcsuf(trie->child[i], ch(i));
    }
}

void calcsufend(Trie *trie) {
    if (!trie) return;

    Trie *suffix = trie->suffix;
    while (suffix) {
        if (suffix->end) break;
        suffix = suffix->suffix;
    }
    trie->sufend = suffix;

    int i;
    for (i = 0; i < 26; ++i) {
        if (trie->child[i]) calcsufend(trie->child[i]);
    }
}

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(&root, 0);
    calcsufend(&root);

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