Cod sursa(job #759868)

Utilizator test13test13 test13 Data 19 iunie 2012 17:57:40
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.87 kb
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cassert>
using namespace std;
#define MAXA 1000001
#define MAXB 10001

struct trie{
    struct trie *f[26]; // directiile catre cele 26 de litere
    struct trie *fail; // muchia de intoarcere in trie
    vector<int>cuv; // lista cuvintelor care se termina pe pozitia respectiva in trie
    int nr; // numarul de aparitii
}*t,*c[MAXA]; //

char a[MAXA],b[MAXB];
int n,p,u,ap[101];

void adauga(int i,char *b){
    trie *g=t;
    int urm;
    while('a'<=*b && *b<='z')
    {
        urm=*b-'a';
        if(g->f[urm]==0)g->f[urm]=new trie;
        g=g->f[urm];
        b++; //urmatorul caracter
    }
        g->cuv.push_back(i);
}

void bfs(){
    trie *g,*v;
    t->fail=t;
    c[p=u=1]=t;
    while(p<=u)
    {
        g=c[p++];
        for(int i=0;i<26;i++)
        if(g->f[i])
        {
            for(v=g->fail;v!=t && v->f[i] == 0;v=v->fail);
            if(v->f[i]!=0 && g->f[i] != v->f[i])v=v->f[i];
            assert(g->f[i]->fail=v);
            c[++u]=g->f[i];
        }
    }
    t->fail=0;
}

void ahocorasick(char *b){
    trie *g=t;
    int urm;
    while('a'<=*b && *b<='z')
    {
        urm=*b-'a';
        while(g!=t && g->f[urm]==0)g=g->fail;
        if(g->f[urm])g=g->f[urm];
        g->nr++;
        b++;
    }
}

void antibfs(){
    trie *g;
    while(u>0)
    {
        g=c[u--];
        if(g->fail)g->fail->nr += g->nr;
        for(int i=0;i<g->cuv.size();i++)ap[g->cuv[i]]=g->nr;
    }
}

int main(){
    freopen("ahocorasick.in","r",stdin);
    freopen("ahocorasick.out","w",stdout);
        scanf("%s ",a);
        scanf("%d ",&n);
    t=new trie; // cream structura
        for(int i=1;i<=n;i++)
        {
            scanf("%s ",b);
            adauga(i,b); // adaugam cuvintul b la structura
        }
    bfs();
    ahocorasick(a);
    antibfs();

        for(int i=1;i<=n;i++)printf("%d\n",ap[i]);
    return 0;
}