Cod sursa(job #2005865)

Utilizator Y0da1NUME JMECHER Y0da1 Data 28 iulie 2017 13:31:06
Problema Aho-Corasick Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 3.52 kb
#include <iostream>
#include <fstream>
#include <string.h>
#include <queue>

using namespace std;
int n, pos=1;
char A [1000005];
char B [10005];
int ans [101];

class nod {
public:
    nod * fail, * sons[26], *parent;
    int eterminal, cnt;
    char c;
    nod()
    {
        memset(sons, 0, sizeof(sons));
        fail = NULL;
        eterminal =0;
        cnt =0;
    }
};
nod T;
queue <nod *> Q;
void ins(char * c, nod * curr)
{
    //cout<<"INSEREZ FIUL "<<c[0]<<" LA NODUL "<<curr<<" ("<<curr->c<<")\n";
    int fiu = (int)(c[0]-'a');
    if(c[0]==0) //caracter nul
    {
        curr->eterminal=pos;
        ++pos;
    }
    if('a'<=c[0] && c[0]<='z')
    {
        if(curr->sons[fiu]==NULL)         //daca nu am mai avut fiul asta
            curr->sons[fiu]=new nod;
            curr->sons[fiu]->c=c[0];
        ins(c+1, curr->sons[fiu]);
    }

}
void befeu (nod * d)
{
    int m=0;
    nod * fail;
    //Q.push(d);
    for(int i=0;i<26;++i)
                if(d->sons[i]!=NULL)    //avem muchie cu litera respectiva
                {
                    d->sons[i]->parent=d->fail;
                    Q.push(d->sons[i]);
                }
    while(!Q.empty())
    {
        d=Q.front();
        //cout<<d->c<<"\n";
        Q.pop();
        if (d==&T)
            continue;
        fail = d->parent;   //luam failu parintelui (cam ca la kmp)
        //cout<<fail<<"\n";
        while(fail->sons[d->c-'a']==NULL && fail != &T)      //calculam fail function cam ca la KMP
        {
            fail=fail->fail;
            //cout<<&T;
            //cout<<fail;
            //cout<<endl;
        }
        d->fail = fail->sons[d->c-'a'];
        if(d->fail == NULL)
            d->fail = &T;
        if(d->fail == d)
            d->fail = &T;
        //cout<<"NODUL "<<d<<"("<<d->c<<") "<<" ARE FAIL "<<d->fail<<" ("<<d->fail->c<<")\n";
        for(int i=0;i<26;++i)
        {
            if(d->sons[i]!=NULL)    //avem muchie cu litera respectiva
                {
                d->sons[i]->parent=d->fail;
                Q.push(d->sons[i]);
                }
        }
    }
}
void befeu_special_doar_pt_infoarena(nod * start)
{
    queue <nod *> Q2;
    nod * d;
    Q2.push(&T);
    while(!Q2.empty())
    {
        d=Q2.front();
        if(d->eterminal>0)
            ans[d->eterminal]=d->cnt;
        Q2.pop();
        for(int i=0;i<26;++i)
        {
            if(d->sons[i]!=NULL)
                Q2.push(d->sons[i]);
        }
    }
}
int main()
{
    ifstream in ("ahocorasick.in");
    ofstream out ("ahocorasick.out");
    in.getline(A, 1000005);
    //in.get();
    in>>n;
    T.fail = &T;
    T.parent = &T;
    T.c='T';
    for(int i=0;i<n;++i)
    {
        in>>B;
        ins(B, &T);
    }
    befeu(&T);
    nod *curr = &T;
    int lg = strlen(A);
    for(int i=0;i<=lg;++i)
    {
        //if(curr->fail->eterminal>0)
          //  curr->fail->cnt++;
        while(curr->sons[A[i]-'a']==NULL && curr!=&T)
        {
            curr=curr->fail;
            if(curr->eterminal>0)   //trebe sa pun si daca NU mergem in fail sa se actualizeze
                curr->cnt++;
        }
        if(curr->sons[A[i]-'a']!=NULL)
        {
            if(curr->fail->eterminal>0)
                curr->fail->cnt++;
            curr=curr->sons[A[i]-'a'];
        }
        if(curr->eterminal>0)
            curr->cnt++;
    }
    befeu_special_doar_pt_infoarena(&T);
    for(int i=1;i<=n;++i)
        out<<ans[i]<<"\n";
    return 0;
}