Cod sursa(job #1851746)

Utilizator cordun_cristinaCristina Maria Cordun cordun_cristina Data 19 ianuarie 2017 23:57:39
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.01 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>

using namespace std;
ifstream f("ahocorasick.in");
ofstream g("ahocorasick.out");

const int Nmax = 10005;
int n, m, sol[Nmax], ic, sc;
char x[1000005], s[Nmax];

struct aho
{
    int n0;
    vector <int> nr;
    aho *sons[26], *fail;
    aho()
    {
        n0 = 0;
        fail = NULL;
        memset(sons,0,sizeof(sons));
    }
};
aho *Q[10005*10005], *r, *p;

void Insert(aho *r, char *p, int i)
{
    if(!isalpha(*p))
    {
        r->nr.push_back(i);
        return;
    }
    int urm = *p-'a';
    if(0==r->sons[urm]) r->sons[urm]=new aho;
    Insert(r->sons[urm],p+1,i);
}

void Read()
{
    f.getline(x,1000005);
    f>>n;
    f.get();
    r = new aho;
    for(int i = 1; i<= n; i++)
    {
        char c[10005];
        f.getline(c,Nmax);
        Insert(r,c,i);
    }
}

void bfs(aho *r)
{
    aho *leu;
    r->fail=r;
    ic=sc=1;
    Q[1]=r;
    for(; ic <= sc; ++ic)
    {
        aho *nod=Q[ic];
        for(int i = 0; i <26; i++) if(nod->sons[i]!=NULL)
        {
            for(leu = nod->fail; leu!=r && leu->sons[i] == NULL; leu = leu->fail);
            if(leu->sons[i] != NULL && leu->sons[i] != nod->sons[i]) leu = leu->sons[i];
            nod->sons[i]->fail = leu;
            Q[++sc]=nod->sons[i];
        }
    }
    r->fail=NULL;
}

void antibfs(aho *r)
{
    for(int i=sc; i > 0; i--)
    {
        aho *nod=Q[i];
        if(nod->fail != NULL) nod->fail->n0 += nod->n0;
        for(int j=0; j < nod->nr.size(); j++) sol[nod->nr[j]] = nod->n0;
    }
}

void Solve()
{
    bfs(r);
    p=r;
    m=strlen(x);
    for(int i=0; i<m; ++i)
    {
        int urm = x[i]-'a';
        for(; p->sons[urm] == NULL && p!=r; p=p->fail);
        if(p->sons[urm] != NULL) p = p->sons[urm];
        ++p->n0;
    }
    antibfs(r);
}

void Print()
{
    for(int i = 1; i <= n; i++) g<<sol[i]<<'\n';
}

int main()
{
    Read();
    Solve();
    Print();
    return 0;
}