Cod sursa(job #1232907)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 24 septembrie 2014 10:59:22
Problema Aho-Corasick Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 4.16 kb
#include <fstream>
//#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <queue>
#include <cassert>

using namespace std;

struct state{
    vector<int> word;

    int fail;
    int total;
    int grad;
    int father;
    char letter;

    int transitions[26];

    state(int father=0,char letter=0): fail(0), total(0), grad(0), father(father), letter(letter) {
        memset(transitions, 0, sizeof(transitions));
    }
};

int frecv[105];

class automaton{
public:
    vector<state> states;

    inline int new_automaton_state(int father=0,char letter=0){
        states.push_back(state(father,letter));

        return (states.size()-1);
    }

public:
    automaton(){
        new_automaton_state();
    }

    inline void add_word(const string &s,int index){
        int k=0;
        for(int i=0;i<s.size();++i){
            if(!states[k].transitions[s[i]-'a']){
                int aux=new_automaton_state(k,s[i]-'a');
                states[k].transitions[s[i]-'a']=aux;
            }

            k=states[k].transitions[s[i]-'a'];
        }

        states[k].word.push_back(index);
    }

    inline void build_fails(){
        queue<int> coada;
        coada.push(0);

        int k;
        int y;
        while(!coada.empty()){
            y=coada.front();
            coada.pop();

            if(states[y].father){
                k=states[states[y].father].fail;

                while(k && !states[k].transitions[states[y].letter])
                    k=states[k].fail;

                if(states[k].transitions[states[y].letter])
                    k=states[k].transitions[states[y].letter];

                states[y].fail=k;
                states[states[y].father].grad++;
                states[states[y].fail].grad++;
            }

            for(int i=0;i<26;i++)
                if(states[y].transitions[i])
                    coada.push(states[y].transitions[i]);
        }
    }

    inline void run_automaton(const string &s){
        int k=0;

        int p;
        vector<int>::iterator it;
        long long steps=0;
        for(int i=0;i<s.size();++i){
            while(k && !states[k].transitions[s[i]-'a'])
                k=states[k].fail;

            if(states[k].transitions[s[i]-'a'])
                k=states[k].transitions[s[i]-'a'];
            states[k].total++;
        }
        //cerr<<"deci "<<steps<<endl;
    }

    inline void calc_final(){
        queue<int> coada;

        bool ok;
        int j;
        for(int i=0;i<states.size();i++){
            ok=true;
            for(j=0;j<26;j++)
                if(states[i].transitions[j]){
                    ok=false;
                    break;
                }

            if(ok)
                coada.push(i);
        }

        int y;
        while(!coada.empty()){
            y=coada.front();
            coada.pop();

            if(states[y].fail){
                states[states[y].fail].total+=states[y].total;
                states[states[y].father].grad--;
                states[states[y].fail].grad--;
            }
            if(states[y].father && !states[states[y].father].grad)
                coada.push(states[y].father);
        }
    }
};

int main()
{
    ifstream cin("ahocorasick.in");
    ofstream cout("ahocorasick.out");

    ios_base::sync_with_stdio(false);
    automaton x;

    string sir;
    getline(cin,sir);

    string curent;

    int n=0;
    cin>>n;

    //cerr<<"gata0"<<endl;
    for(int i=1;i<=n;i++){
        cin>>curent;

        x.add_word(curent,i);
        //cerr<<"gata1 "<<i<<endl;
    }
    //cerr<<"gata2"<<endl;

    x.build_fails();

    //cerr<<"gata3"<<endl;
    x.run_automaton(sir);
    x.calc_final();

    vector<int>::iterator it;
    for(int i=0;i<x.states.size();i++){
        for(it=x.states[i].word.begin();it!=x.states[i].word.end();it++)
            frecv[*it]+=x.states[i].total;
    }

    //cerr<<"gata4"<<endl;
    for(int i=1;i<=n;i++)
        cout<<frecv[i]<<'\n';

    //cerr<<"gata5"<<endl;
    cin.close();
    cout.close();
    return 0;
}