Cod sursa(job #1970316)

Utilizator FlorinHajaFlorin Gabriel Haja FlorinHaja Data 19 aprilie 2017 10:41:07
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.08 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

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

int i, j, m, ind, n, st, dr;
int sol[105];
char reff[1000005], s[10005];

struct trie {
    int nfii, cnt;
    trie *urm[30], *fail;
    vector <int> fnd;
    trie() {
        fail = 0;
        nfii = cnt = 0;
        memset(urm, 0, sizeof(urm));
    }
};
trie *inc, *coada[1000005], *x, *y, *tmp, *t;

void inser(trie *t, char *s) {
    while (*s >= 'a') {
        int c = *s-'a';
        if (t -> urm[c] == 0)
            t -> urm[c] = new trie, t->nfii++;
        t = t -> urm[c];
        s++;
    }
    t -> fnd.push_back(ind);
}

void bfs() {
    st = 0;
    coada[st] = inc;
    inc -> fail = inc;
    while (st <= dr) {
        x = coada[st++];
        for (i = 0; i < 26; i++) {
            if (x -> urm[i] == 0) continue;
            y = x -> urm[i];
            tmp = x -> fail;
            while (tmp != inc && tmp -> urm[i] == 0) tmp = tmp -> fail;
            if ((tmp -> urm[i] != NULL) && tmp -> urm[i] != y)
                tmp = tmp -> urm[i];
            x -> urm[i] -> fail = tmp;
            coada[++dr] = y;
        }
    }
    inc -> fail = 0;
}

void bfsinv() {
    for (i = dr; i >= 0; i--) {
        tmp = coada[i];
        if (tmp -> fail!= 0)
            tmp -> fail -> cnt += tmp -> cnt;
        for (j = 0; j < tmp -> fnd.size(); j++)
            sol[ tmp->fnd[j] ] = tmp -> cnt;
    }
}

int main() {
    inc = new trie;
    f.getline(reff+1, sizeof(reff));
    f >> m;f.get();
    for (i = 1; i <= m; i++) {
        f.getline(s+1, sizeof(s));
        ind = i;
        inser(inc, s+1);
    }
    bfs();
    n = strlen(reff+1);
    tmp = inc;
    for (i = 1; i <= n; i++) {
        ind = reff[i]-'a';

        while (tmp -> urm[ind] == 0 && tmp != inc)
            tmp = tmp -> fail;
        if (tmp->urm[ind] != 0)
            tmp = tmp -> urm[ind];
        tmp -> cnt++;
    }
    bfsinv();
    for (i = 1; i <= m; i++)
        g << sol[i] << '\n';
}