Cod sursa(job #2022670)

Utilizator DorelBarbuBarbu Dorel DorelBarbu Data 16 septembrie 2017 22:13:58
Problema Aho-Corasick Scor 95
Compilator cpp Status done
Runda Arhiva educationala Marime 3.71 kb
#include <vector>
#include <iostream>
#include <fstream>
#include <queue>
#include <cstring>
using namespace std;

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

const int ALPHALEN = 26, MAXN = 100, MAXLEN = 10000, MAXLENTEXT=1e6;

int n, ans[MAXN+1];
char text[MAXLENTEXT+1];


struct node
{
    vector <int> output;
    int index;
    node* next[ALPHALEN+1];
    node* fail;
    node()
    {
        for(int i = 0; i < ALPHALEN; i++)
            next[i] = NULL;
    }
};

struct finiteAutomata
{
    node* root;
    int numStates;
    finiteAutomata()
    {
        root = new node;
        root->index = 0;
        numStates = 0;
    }

    void addWord(node* &root, char* s, int k)
    {
        if(root == NULL)
        {
            root = new node;
            numStates++;
            root->index = numStates;
        }

        if(strlen(s) == 1)
        {
            root->output.push_back(k);
            return;
        }

        addWord(root->next[s[1]-'a'],s+1,k);
    }

    void buildFailFunction()
    {
        queue <node*> Q;

        for(int i = 0; i < ALPHALEN; i++)
            if(root->next[i] != NULL)
            {
                root->next[i]->fail = root;
                //printf("f(%d) = %d\n",root->next[i]->index,root->index);
                Q.push(root->next[i]);
            }

        while(Q.empty() == false)
        {
            node* curr = Q.front();
            Q.pop();

            for(int i = 0; i < ALPHALEN; i++)
            {
                if(curr->next[i] != NULL)
                {
                    Q.push(curr->next[i]);
                    node* state= curr->fail;

                    while(state != root && state->next[i] == NULL)
                        state = state->fail;

                    node *s, *fs;
                    s = curr->next[i];
                    fs = state->next[i];

                    if(fs == NULL)
                    {
                        s->fail = root;
                    }
                    else
                    {
                        s->fail = fs;
                        s->output.insert(s->output.begin(),fs->output.begin(),fs->output.end());
                    }

                    //printf("fail(%d) = %d\n",s->index,fs->index);
                }
            }
        }

        for(int i = 0; i < ALPHALEN; i++)
            if(root->next[i] == NULL)
                root->next[i] = root;
    }

     void matchText(char* text)
        {
            int textLen = strlen(text);
            node* state = root;
            for(int i = 0; i < textLen; i++)
            {
                char currChar = text[i];
                while(state->next[currChar-'a'] == NULL)
                    state = state->fail;

                state = state->next[currChar-'a'];

                if(state->output.empty() == false)
                {
                    for(int word: state->output)
                        ans[word]++;
                }
            }
        }


    void afis(node* root)
    {
        if(root == NULL)
            return;

        for(int word: root->output)
            cout<<word<<endl;

        for(int i = 0; i < ALPHALEN; i++)
            afis(root->next[i]);
    }
};

finiteAutomata T;

char buff[MAXLEN+1];

void citire()
{
    in>>text;
    in>>n;
    for(int i = 1; i <= n; i++)
    {
        in>>buff;
        T.addWord(T.root->next[buff[0]-'a'],buff,i);
    }
}

int main()
{
    citire();
    T.buildFailFunction();
    T.matchText(text);
    //cout<<"Number of states is: "<<T.numStates<<endl;
    for(int i = 1; i <= n; i++)
        out<<ans[i]<<endl;
    return 0;
}