Cod sursa(job #1099642)

Utilizator mirceadinoMircea Popoveniuc mirceadino Data 6 februarie 2014 00:47:06
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.51 kb
#include<cstdio>
#include<vector>
#include<cstring>

using namespace std;

const int NMAX = 100+2;     //Numarul de cuvinte
const int AMAX = 26;        //Marimea alfabetului
const int CMAX = 10000+2;   //Lungimea unui cuvant
const int LMAX = 1000000+2; //Lungimea sirului

struct Node
{
    vector<int> V;   //Cuvintele care se termina in nodul curent
    Node *Fii[AMAX]; //Fiii nodului curent
    Node *Fail;      //Fail-ul nodului curent
    int NrPotr;      //Numarul de potriviri din nodul curent sau din fii
    Node()
    {
        Fail=NULL;
        memset(Fii,0,sizeof(Fii));
        NrPotr=0;
    }
};

Node *Root;
int N,L,Solutie[NMAX];
char Sir[LMAX],Cuvant[CMAX];

void Insereaza(char *Cuvant,int ind) //Insereaza cuvantul cu indicele ind in trie
{
    Node *P;
    int c;
    for(P=Root; *Cuvant; Cuvant++,P=P->Fii[c])
    {
        c=*Cuvant-'a';
        if(P->Fii[c]==NULL) P->Fii[c]=new Node;
    }
    P->V.push_back(ind);
}

Node *Q[CMAX*CMAX]; //Coada
int I,S; //Inceputul si sfarsitul cozii

void BFS()
{
    int i;
    Node *CFail,*X,*Y;

    Root->Fail=Root;

    Q[I=S=0]=Root;

    while(I<=S)
    {
        X=Q[I++];

        for(i=0; i<AMAX; i++)
        {
            Y=X->Fii[i]; //Cautam fail pentru nodul-fiu Y al lui X
            if(Y==NULL) continue;

            for(CFail=X->Fail; CFail->Fii[i]==NULL && CFail!=Root; CFail=CFail->Fail);
            if(CFail->Fii[i]!=NULL && CFail->Fii[i]!=Y) CFail=CFail->Fii[i];
            Y->Fail=CFail;
            Q[++S]=Y;
        }
    }

    Root->Fail=NULL;
}

void AntiBFS()
{
    vector<int>::iterator it;
    Node *X;

    while(S>=0)
    {
        X=Q[S--];
        if(X->Fail!=NULL) X->Fail->NrPotr+=X->NrPotr;
        for(it=X->V.begin(); it!=X->V.end(); it++)
            Solutie[*it]=X->NrPotr;
    }
}

void AhoCorasick()
{
    Node *X;
    int i,c;

    BFS();

    L=strlen(Sir);
    X=Root;

    for(i=0; i<L; i++)
    {
        c=Sir[i]-'a';
        for(; X->Fii[c]==NULL && X!=Root; X=X->Fail);
        if(X->Fii[c]!=NULL) X=X->Fii[c];
        X->NrPotr++;
    }

    AntiBFS();
}

int main()
{
    int i;

    freopen("ahocorasick.in","r",stdin);
    freopen("ahocorasick.out","w",stdout);

    scanf("%s",Sir);
    scanf("%d",&N);

    Root=new Node;

    for(i=1; i<=N; i++)
    {
        scanf("%s",Cuvant);
        Insereaza(Cuvant,i);
    }

    AhoCorasick();

    for(i=1; i<=N; i++)
        printf("%d\n",Solutie[i]);

    return 0;
}