Cod sursa(job #2442880)

Utilizator Alex_BubBuburuzan Alexandru Alex_Bub Data 25 iulie 2019 17:11:59
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.32 kb
#include <fstream>
#include <vector>

using namespace std;

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

const int LMax = 10002;

char S[1000005], W[LMax + 5];
int N, Sol[105];

struct Trie
{
    int val; char l; vector <int> List;
    Trie * Son[28], * Match, * Tata;

    Trie()
    {
        val = 0; Match = Tata = NULL; l = 0;

        for(int i = 0; i < 28; i++)
            Son[i] = NULL;
    }
};
Trie * Root = new Trie;

vector <Trie*> V[LMax + 5];

void Add(Trie * & Nod, int lev, char * T, int i)
{
    if(*T == 0)
    {
        Nod -> List.push_back(i);
        return;
    }
    char c = *T - 'a';

    if(Nod -> Son[c] == NULL)
    {
        Nod -> Son[c] = new Trie;
        V[lev + 1].push_back(Nod -> Son[c]);

        Nod -> Son[c] -> Tata = Nod;
        Nod -> Son[c] -> l = *T;
    }
    Add(Nod -> Son[c], lev + 1, T + 1, i);
}

void BFS()
{
    for(int i = 2; i <= LMax; i++)
        for(auto Nod : V[i])
        {
            char c = Nod -> l - 'a';
            Trie * Finder = Nod -> Tata -> Match;

            while(Finder -> Son[c] == NULL && Finder != Root)
                Finder = Finder -> Match;

            if(Finder -> Son[c] == NULL)
                Nod -> Match = Root;
            else
                Nod -> Match = Finder -> Son[c];
        }
}

void Solve()
{
    Trie * Nod = Root;

    for(int i = 0; S[i]; i++)
    {
        char c = S[i] - 'a';

        while(Nod -> Son[c] == NULL && Nod != Root)
            Nod = Nod -> Match;

        if(Nod -> Son[c])
        {
            Nod = Nod -> Son[c];
            Nod -> val++;
        }
    }
}

void Spread()
{
    for(int i = LMax; i > 0; i--)
        for(auto Nod : V[i])
        {
            for(auto j : Nod -> List)
                Sol[j] = Nod -> val;

            Nod -> Match -> val += Nod -> val;
        }
}

int main()
{
    fin >> S >> N;

    for(int i = 1; i <= N; i++)
        fin >> W, Add(Root, 0, W, i);

    Root -> Match = Root -> Tata = Root;

    for(int i = 0; i < 28; i++)
    {
        if(Root -> Son[i] != NULL)
            Root -> Son[i] -> Match = Root;
    }
    BFS(); Solve(); Spread();

    for(int i = 1; i <= N; i++)
        fout << Sol[i] << '\n';

    fin.close();
    fout.close();

    return 0;
}