Cod sursa(job #1761786)

Utilizator oldatlantianSerban Cercelescu oldatlantian Data 22 septembrie 2016 21:00:59
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2 kb
#include <bits/stdc++.h>
using namespace std;

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

const int SIGM = 26;

struct Aho {
    vector<int> ordbok;
    Aho *t[SIGM];
    Aho *fail;
    int  match;

    inline Aho() {
        memset(t, 0x00, sizeof(t));
        match = 0;
        fail = NULL;
    }
};

int pindex;
Aho *rt;

int ant[105];
vector<Aho*> rq;

void put(const string &arg) {
    Aho *now = rt;
    for(const char &ch: arg) {
        if(!now->t[ch-'a'])
            now->t[ch-'a'] = new Aho();
        now = now->t[ch-'a'];
    }
    now->ordbok.push_back(++pindex);
}

void ave(void) {
    queue<Aho*> q;
    Aho *now, *tmp;

    q.push(rt);
    rt->fail = rt;

    while(!q.empty()) {
        now = q.front();
        q.pop();

        for(int i=0; i<SIGM; ++i) if(now->t[i]) {
            q.push(now->t[i]);
            rq.push_back(now->t[i]);
            tmp = now->fail;

            while(tmp!=rt && !tmp->t[i])
                tmp = tmp->fail;
            if(tmp->t[i]!=NULL && tmp->t[i]!=now->t[i])
                tmp = tmp->t[i];

            now->t[i]->fail = tmp;
        }
    }

    rt->fail = NULL;
}

void caesar(const string &txt) {
    Aho *now = rt;

    for(const auto &ch: txt) {
        while(now!=rt && !now->t[ch-'a'])
            now = now->fail;

        if(now->t[ch-'a'])
            now = now->t[ch-'a'];
        ++ now->match;
    }
}

void imperator(void) {
    for(int i=rq.size()-1; i>=0; --i) {
        if(rq[i]->fail)
            rq[i]->fail->match += rq[i]->match;
        for(auto &j: rq[i]->ordbok)
            ant[j]+= rq[i]->match;
    }
}

int main(void) {
    string txt, pat;
    int m;

    rt = new Aho();

    fi >> txt >> m;
    for(int i=1; i<=m; ++i) {
        fi >> pat;
        put(pat);
    }

    ave();
    caesar(txt);
    imperator();

    for(int i=1; i<=m; ++i)
        fo << ant[i] << '\n';

    cout << "Odin hjalpa!" << '\n';

    return 0;
}