Cod sursa(job #660346)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 12 ianuarie 2012 16:00:25
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.65 kb
#include <cstdio>
#include <queue>
#include <cstring>
#include <vector>

#define LMax 1000005
#define WMax 10005
#define NMax 105
#define QMax 1000010

using namespace std;

struct Trie
{
    vector <int> S;
    int NS;
    Trie *Son[26], *Fail;
    Trie ()
    {
        NS=0;
        Fail=NULL;
        memset (Son, 0, sizeof (Son));
    }
};
Trie *A;
Trie* Q[QMax];
int ND, Frequence[NMax], QL, QR;
char String[LMax];

inline int Code (char C)
{
    return ((int)C-(int)'a');
}

inline void Insert (Trie *Node, char *Letter, int i)
{
    if (*Letter=='\n')
    {
        Node->S.push_back (i);
        return;
    }
    int C=Code (*Letter);
    if (Node->Son[C]==NULL)
    {
        Node->Son[C]=new Trie;
    }
    Insert (Node->Son[C], Letter+1, i);
}

void Initialize ()
{
    A->Fail=A;
    QL=QR=1;
    Q[QL]=A;
}

void BFS ()
{
    Initialize ();
    while (QL<=QR)
    {
        Trie *Node=Q[QL++];
        for (int i=0; i<26; ++i)
        {
            Trie *CFail;
            if (Node->Son[i]==NULL)
            {
                continue;
            }
            for (CFail=Node->Fail; CFail!=A and CFail->Son[i]==NULL; CFail=CFail->Fail);
            if (CFail->Son[i]!=NULL and CFail->Son[i]!=Node->Son[i])
            {
                CFail=CFail->Son[i];
            }
            Node->Son[i]->Fail=CFail;
            Q[++QR]=Node->Son[i];
        }
    }
    A->Fail=NULL;
}

void ReverseBFS ()
{
    while (QR>0)
    {
        Trie *Node=Q[QR--];
        if (Node->Fail!=NULL)
        {
            Node->Fail->NS+=Node->NS;
        }
        for (unsigned i=0; i<Node->S.size (); ++i)
        {
            Frequence[Node->S[i]]=Node->NS;
        }
    }
}

void AhoCorasick ()
{
    BFS ();
    int L=strlen (String);
    Trie *Node=A;
    for (int i=0; i<L; ++i)
    {
        int C=Code (String[i]);
        for (;Node!=A and Node->Son[C]==NULL; Node=Node->Fail);
        if (Node->Son[C]!=NULL)
        {
            Node=Node->Son[C];
        }
        ++Node->NS;
    }
    ReverseBFS ();
}

void Read ()
{
    A=new Trie;
    freopen ("ahocorasick.in", "r", stdin);
    scanf ("%s", String);
    scanf ("%d", &ND);
    for (int i=1; i<=ND; ++i)
    {
        char Word[WMax];
        memset (Word, 0, sizeof (Word));
        scanf ("%s", Word);
        strcat (Word, "\n");
        Insert (A, Word, i);
    }
}

void Print ()
{
    freopen ("ahocorasick.out", "w", stdout);
    for (int i=1; i<=ND; ++i)
    {
        printf ("%d\n", Frequence[i]);
    }
}

int main()
{
    Read ();
    AhoCorasick ();
    Print ();
    return 0;
}