Cod sursa(job #1994271)

Utilizator ArctopusKacso Peter-Gabor Arctopus Data 24 iunie 2017 15:20:41
Problema Aho-Corasick Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.1 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <windows.h>

using namespace std;

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

const int NLIM = 1e6 + 10;


int gi;

vector< int > graph[NLIM];
int parent[NLIM];
int suff[NLIM];
int nodnr = 1;
char nodc[NLIM];
int depth[NLIM];
int wend[NLIM];

int res[NLIM];

int N;


string str;
string s;

void addTrie( int nod, int idx )
{
  //  for( int i = 0; i < depth[nod]; ++i )
        //cout << " ";
    //cout << nod << " " << nodc[nod] << " " << idx << " ";
    int found = 0;
    for( int j = 0; j < graph[nod].size() && !found; ++j )
    {
        int nnod = graph[nod][j];
        if( nodc[nnod] == s[idx] )
        {
            found = nnod;
        }
    }

    //cout << found << " * ";

    if( found )
    {
        // last
        if( idx == s.size() - 1 )
        {
            wend[found] = gi;
            //cout << " |wendf| " << found << " " << wend[found] << " ";
        }
        else
        {
            addTrie( found, idx + 1 );
        }
    }
    if( !found )
    {
       // cout << " |add| ";
        ++nodnr;
        graph[nod].push_back( nodnr );
        depth[nodnr] = depth[nod] + 1;
        nodc[nodnr] = s[idx];

        parent[nodnr] = nod;

      //  cout << nodnr << " ";

        if( idx == s.size() - 1 )
        {
            wend[nodnr] = gi;
            //cout << " |wendn| " << nodnr << " " << wend[nodnr] << " ";
        }
        else
        {
            addTrie( nodnr, idx + 1 );
        }
    }

    //cout << "\n";
}


void findSuff( int nod )
{
   // cout << " | ";
    //cout << nod << " " << nodc[nod] << "\n";
    int tnod = parent[nod];
    bool f = 0;
    while( tnod != -1 && !f )
    {
        for( int j = 0; j < graph[tnod].size(); ++j )
        {
            int nnod = graph[tnod][j];
            if( nodc[nnod] == nodc[nod] && nod != nnod )
            {
                suff[nod] = nnod;
                return;
            }
        }

        if( !suff[tnod] )
        {
            //Sleep( 10000 );
            findSuff( tnod );

        }
        tnod = suff[tnod];
        //cout << tnod << " ";
    }
    //cout << "\n";
    suff[nod] = 1;
}

void bfs( int nod )
{
    //cout << nod << "\n";
    if( nod != 1 && !suff[nod] )
    {
        findSuff( nod );
    }


    for( int j = 0; j < graph[nod].size(); ++j )
    {
        int nnod = graph[nod][j];
        bfs( nnod );
    }
}

int dirNode( int nod, char c )
{
    for( int j = 0; j < graph[nod].size(); ++j )
    {
        int nnod = graph[nod][j];
        if( nodc[nnod] == c )
        {
            return nnod;
        }
    }

    return 0;
}

int nextNode( int nod, char c )
{

    while( nod != -1 )
    {
        int dirn = dirNode( nod, c );
        if( dirn )
        {
            return dirn;
        }

        nod = suff[nod];
    }

    return 1;
}



int main()
{
    parent[1] = -1;
    suff[1] = -1;
    depth[1] = 0;
    nodc[1] = '-';


    fin >> str;
    fin >> N;
    for( gi = 1; gi <= N; ++gi )
    {
        fin >> s;

        //cout << s << "\n";
        addTrie( 1, 0 );

    }


    bfs( 1 );


    /*/
    for( int i = 1; i <= nodnr; ++i )
    {
        cout << i << " " << nodc[i] << ": ";
        for( int j = 0; j < graph[i].size(); ++j )
        {
            cout << nodc[graph[i][j]] << " ";
        }
        cout << "\n";
        cout << suff[i] << " " << nodc[suff[i]] << "\n";
    }
    //*/

    int hnod = 1;
    //cout << hnod << "\n";
    for( gi = 0; gi < str.size(); ++gi )
    {
        // find next node

        hnod = nextNode( hnod, str[gi] );

        // results:
        int tnod = hnod;
        //cout << gi << ": ";
        while( tnod != 1 )
        {
            if( wend[tnod] )
                ++res[wend[tnod]];
            tnod = suff[tnod];
        }
        //cout << "\n";
    }


    for( int i = 1; i <= N; ++i )
    {
        fout << res[i] << "\n";
    }

    return 0;
}