Cod sursa(job #2288809)

Utilizator mateibanuBanu Matei Costin mateibanu Data 23 noiembrie 2018 22:33:09
Problema Aho-Corasick Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.49 kb
/*
#include <bits/stdc++.h>

using namespace std;

#define LA (int)(2+1e6)
#define LC (int)(2+1e4)

char a[LA],c[LC];
int n,m,p[LC],r;

void prefixe(){
    int i,k=0;
    for (i=0;i<=n;i++) p[i]=0;
    for (i=2;i<=n;i++){
        for (;k!=0&&c[k+1]!=c[i];) k=p[k];
        if (c[k+1]==c[i]) k++;
        p[i]=k;
    }
}

void potrivire(){
    int k=0,i;
    r=0;
    for (i=1;i<=m;i++){
        for (;k!=0&&c[k+1]!=a[i];) k=p[k];
        if (c[k+1]==a[i]) k++;
        if (k==n) r++;
    }
}

int main()
{
    freopen("ahocorasick.in","r",stdin);
    freopen("ahocorasick.out","w",stdout);
    int nr,i;
    scanf("%s%d",a+1,&nr);
    m=strlen(a+1);
    for (i=1;i<=nr;i++){
        scanf("%s",c+1);
        n=strlen(c+1);
        prefixe();
        potrivire();
        printf("%d\n",r);
    }
    return 0;
}*/
#include <cstdio>

#include <cstring>

#include <cctype>

#include <vector>

#define DL 1000005

#define DN 10005

#define DA 26//dimensiunea alfabetului

using namespace std;



int lg,n,l,final[DN],ic,sc;

char tx[DL],c[DN];



struct ac {

    vector<int> nd;//sirurile care se termina in nodul curent

    int n0;//numarul de potriviri din nodul curent sau din fii lui

    ac *f[DA],*fail;

    ac() {

        n0=0;

        fail=NULL;

        memset(f,0,sizeof(f));

    }

} *q[DN*DN],*t,*p;





void ins(ac *t,char *p,int i) {//inserarea se face ca si la trie

    if(!isalpha(*p)) {

        t->nd.push_back(i);

        return;

    }

    int urm=*p-'a';

    if(0==t->f[urm]) t->f[urm]=new ac;

    ins(t->f[urm],p+1,i);

}



void bfs(ac *t) {

    ac *dolar;//unde o sa mearga fail-ul fiecarui nod

    t->fail=t;

    for(q[ic=sc=1]=t;ic<=sc;++ic) {

        ac *fr=q[ic];

        for(int i=0; i<DA; ++i) if(fr->f[i]!=NULL) {//nodul caruia ii cautam fail-ul

            //ne ducem in fail pana gasim un nod care are ca fiu ultima litera a nodului sau pana ajungem in radacina

            for(dolar=fr->fail;dolar!=t && dolar->f[i]==NULL;dolar=dolar->fail);



            if(dolar->f[i]!=NULL && dolar->f[i]!=fr->f[i]) dolar=dolar->f[i];

            fr->f[i]->fail=dolar;

            q[++sc]=fr->f[i];

        }

    }

    t->fail=NULL;

}





void antibfs(ac *t) {

    //parcurgem nodurile in ordinea inversa a bfs-ului astfel fiecare nod va fi parcurs dupa ce au

    //fost parcursi toti fii lui si astfel putem calcula n0

    for(int i=sc; i>0; --i) {

        ac *fr=q[i];

        if(fr->fail!=NULL) fr->fail->n0+=fr->n0;

        //parcurgem toate cuvintele care se termina in nodul curent si actualizam solutia

        for(int j=0; j<fr->nd.size(); ++j) final[fr->nd[j]]=fr->n0;

    }

}



int main()

{

    freopen("ahocorasick.in","r",stdin);

    freopen("ahocorasick.out","w",stdout);

    scanf("%s",tx);

    scanf("%d",&n);

    t=new ac;

    for(int i=1; i<=n; ++i) {

        scanf("%s",c);

        ins(t,c,i);

    }

    bfs(t);

    p=t;

    lg=strlen(tx);

    for(int i=0; i<lg; ++i) {

        int urm=tx[i]-'a';

        //cautam o muchie pe care sa putem merge in jos

        for(;p->f[urm]==NULL && p!=t;p=p->fail);

        if(p->f[urm]!=NULL) p=p->f[urm];

        ++p->n0;//creste numarul de potriviri din nodul curent

    }

    antibfs(t);

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

    return 0;

}
    cout << "Hello world!" << endl;
    return 0;
}