Cod sursa(job #1367344)

Utilizator CosminRusuCosmin Rusu CosminRusu Data 1 martie 2015 20:01:49
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.21 kb
#include <iostream>
#include <fstream>
#include <string.h>
#include <vector>

using namespace std;

ifstream fin("ahocorasick.in");
ofstream fout("ahocorasick.out");

const int maxn = 1000005;
const int maxw = 10005;
const int sigma = 26;

struct node {
    node *sons[sigma];
    node *fail;
    int matches;
    vector <int> ind;
    node () {
        memset(sons, 0, sizeof(sons));
        fail = NULL;
        matches = 0;
    }
} *root;

char text[maxn], word[maxw];
int n, ans[105];
vector <node *> q;

inline void _insert(node *root, char *s, int ind) {
    if(!*s) {
        root->ind.push_back(ind);
        return;
    }
    int son = *s - 'a';
    if(!root->sons[son])
        root->sons[son] = new node();
    _insert(root->sons[son], s + 1, ind);
}

inline void bfs() {
    q.push_back(root);
    root->fail = root;
    for(int i = 0 ; i < q.size() ; ++ i) {
        node *aux = q[i];
        for(int son = 0 ; son < sigma ; ++ son)
            if(aux->sons[son]) {
                node *k = aux->fail;
                while(k != root && !k->sons[son])
                    k = k->fail;
                if(k->sons[son] != aux->sons[son] && k->sons[son])
                    k = k->sons[son];
                aux->sons[son]->fail = k;
                q.push_back(aux->sons[son]);
            }
    }
}

inline void ahocorasick(char *t) {
    node *k = root;
    for( ; *t ; ++ t) {
        int son = *t - 'a';
        while(k != root && !k->sons[son])
            k = k->fail;
        if(k->sons[son])
            k = k->sons[son];
        ++ k->matches;
    }
}

inline void antibfs() {
    for(int i = q.size() - 1 ; i >= 0 ; -- i) {
        node *aux = q[i];
        aux->fail->matches += aux->matches;
        for(int j = 0 ; j < aux->ind.size() ; ++ j) {
            ans[aux->ind[j]] = aux->matches;
        }
    }
}

int main() {
    root = new node();
    fin.getline(text + 1, maxn);
    fin >> n;
    fin.get();
    for(int i = 1 ; i <= n ; ++ i) {
        fin.getline(word + 1, maxn);
        _insert(root, word + 1, i);
    }
    bfs();
    ahocorasick(text + 1);
    antibfs();
    for(int i = 1 ; i <= n ; ++ i)
        fout << ans[i] << '\n';
}