Cod sursa(job #1232604)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 23 septembrie 2014 14:56:44
Problema Aho-Corasick Scor 95
Compilator cpp Status done
Runda Arhiva educationala Marime 3.22 kb
#include <fstream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <queue>

using namespace std;

struct state{
    vector<int> word;

    int fail;
    int fail2;
    int father;
    char letter;

    int transitions[26];

    state(int father=0,char letter=0): fail(0), fail2(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;

                //Calculam states[y].fail2
                if(states[states[y].fail].word.size())
                    states[y].fail2=states[y].fail;
                else
                    states[y].fail2=states[states[y].fail].fail2;

                //cout<<"states["<<y<<"].fail2 = "<<states[y].fail2<<endl;
            }

            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;
        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'];

            p=k;
            while(p){
                for(it=states[p].word.begin();it!=states[p].word.end();it++)
                    frecv[*it]++;
                p=states[p].fail2;
            }
        }
    }
};

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;

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

        x.add_word(curent,i);
    }
    x.build_fails();

    x.run_automaton(sir);

    for(int i=1;i<=n;i++)
        cout<<frecv[i]<<'\n';

    cin.close();
    cout.close();
    return 0;
}