Cod sursa(job #981836)

Utilizator dicu_dariaDaria Dicu dicu_daria Data 7 august 2013 23:22:33
Problema Aho-Corasick Scor 95
Compilator cpp Status done
Runda Arhiva educationala Marime 2.85 kb
#include <iostream>
#include <fstream>
#include <queue>
#include <cstring>
#include <iomanip>
#include <vector>
#include <cstdio>
#define fiu fii[index(s[p])]
#define nxt nod->fii[i]
using namespace std;

string s, input, A;
int l, currWord, fr[510], w, t;

int index(char x)
{
    if(x == '-') return 62;
    if(x <= '9' and x >= '0') return (x - '0');
    if(x <= 'Z' and x >= 'A') return (x - 'A' + 10);
    return (x - 'a' + 36);
}

struct Arb {
    //Arb *fii[63], *f;
    Arb *fii[80], *f;
    int cnt;
    vector<int>out;
    Arb()
    {
        out.clear();
        cnt = 0;
        memset(fii, 0, sizeof(fii));
        f = 0;
    }
};

Arb* fail;
Arb* root = new Arb;
queue<Arb*>Q;

void Solutie(Arb *nod)
{
    int i;
    for(i = 0; i < nod->out.size(); i++) fr[nod->out[i]] += nod->cnt;
    for(i = 0; i < 80; i++)
        if(nod->fii[i] != 0)
            Solutie(nod->fii[i]);
}

void Failure()
{
    int i;
    Arb* nod;
    root->f = root;
    while(!Q.empty()) Q.pop();
    Q.push(root);
    while(!Q.empty())
    {
        nod = Q.front();
        Q.pop();
        for(i = 0; i < 80; i++)
            if(nxt)
            {
                Q.push(nxt);
                fail = nod->f;
                while(fail != root and !fail->fii[i])
                    fail = fail->f;
                if(nod == root)
                    nxt->f = root;
                else if(fail->fii[i])
                {
                    nxt->f = fail->fii[i];
                    nxt->out.insert(nxt->out.end(), fail->fii[i]->out.begin(), fail->fii[i]->out.end());
                }
                else
                    nod->fii[i]->f = root;
            }
    }

}

int main()
{
    int i, p;
    Arb* nod;

    ifstream fi("ahocorasick.in");
    ofstream fo("ahocorasick.out");

    fi >> A;
    memset(fr, 0, sizeof(fr));
    fi >> w;
    getline(fi, s);
    for(i = 0; i < w; i++)
    {
        getline(fi, s);
        currWord = i;
        l = s.length();
        for(nod = root, p = 0; p <= l; p++)
        {
            if(p == l)
            {
                nod->out.push_back(currWord);
                break;
            }
            if(!nod->fiu) nod->fiu = new Arb;
            nod = nod->fiu;
        }
    }
    Failure();

    s = A;
    l = s.length();
    //Solve(root, 0);
    //STACK OVERFLOW


    for(p = 0, nod = root; p <= l; p++)
    {
        nod->cnt++;
        if(p == l) break;
        if(!nod->fiu)
        {
            fail = nod->f;
            while(fail != root and !fail->fiu) fail = fail->f;
            if(fail->fiu)
                nod = fail->fiu;
            else
                nod = root;
        }
        else nod = nod->fiu;
    }

    Solutie(root);
    for(i = 0; i < w; i++) fo << fr[i] << "\n";
    return 0;
}