Cod sursa(job #1958489)

Utilizator FlorinHajaFlorin Gabriel Haja FlorinHaja Data 8 aprilie 2017 13:56:21
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.01 kb
#include <fstream>
#include <cstring>
#include <vector>

using namespace std;

ifstream f("ahocorasick.in");
ofstream g("ahocorasick.out");

const int ln = 10005, la = 1000005;
struct trie {
    vector<int> care;
    int nr;
    trie *urm[30], *fail;
    trie() {
        fail = 0;
        nr = 0;
        memset(urm, 0, sizeof(urm));
    }
};
trie *inc, *coada[ln*ln], *p;
int n, i, j, st, dr, sol[ln], N;
char orig[la], s[ln];

void pune(trie *t, char *s, int ind) {
    if (*s < 'a') {
        t -> care.push_back(ind);
        return;
    }
    int c = *s - 'a';
    if (t -> urm[c] == 0)
        t -> urm[c] = new trie;
    pune(t -> urm[c], s+1, ind);
}

void bfs(trie *t) {
    trie *y, *dolar, *fr;
    coada[st=dr=0] = t;
    t -> fail = t;
    while (st <= dr) {
        fr = coada[st++];
        for (i = 0; i < 26; i++) {
            if (fr -> urm[i] == 0) continue;
            y = fr -> urm[i];
            dolar = fr -> fail;
            while (dolar -> urm[i] == NULL && dolar != t)
                dolar = dolar -> fail;
            if (dolar -> urm[i] != NULL && (dolar -> urm[i]) != y)
                dolar = dolar -> urm[i];
            y -> fail = dolar;

            coada[++dr] = y;
        }
    }
    t -> fail = NULL;
}

void bfsinvers() {
    for (;dr > 0; dr--) {
        p = coada[dr];
        if (p -> fail != NULL)
            p -> fail -> nr += p -> nr;
        for (i = 0; i < p -> care.size(); i++)
            sol[ p -> care[i] ] = p -> nr;
    }
}

int main() {
    inc = new trie;
    f >> orig >> n;
    for (i = 1; i <= n; i++) {
        f >> s;
        pune(inc, s, i);
    }
    N = strlen(orig);
    bfs(inc);
    p = inc;
    int c;
    for (i = 0; i < N; i++) {
        c = orig[i]-'a';
        while (p -> urm[c] == NULL && p != inc)
            p = p -> fail;
        if (p -> urm[c] != NULL)
            p = p -> urm[c];
        p -> nr++;
    }
    bfsinvers();
    for (i = 1; i <= n; i++)
        g << sol[i] << '\n';
}