Cod sursa(job #2493278)

Utilizator DavidLDavid Lauran DavidL Data 16 noiembrie 2019 11:17:32
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.54 kb
#include <bits/stdc++.h>
using namespace std;
ifstream fi("ahocorasick.in");
ofstream fo("ahocorasick.out");
#define cin fi
#define cout fo

struct Trie {
    int rezNod = 0;
    vector <int> ceCuv;
    Trie *fiu[30] = {0};
    Trie *fail = 0;
};

int m, n;
char cuv[10005];
char A[1000005];
int ans[105];
Trie *T = new Trie;


void adauga(Trie *nod, int poz, int careCuv)
{
    if (poz == strlen(cuv + 1))
    {
        nod->ceCuv.push_back(careCuv);
        return;
    }

    if (nod->fiu[cuv[poz + 1] - 'a'] == 0)
        nod->fiu[cuv[poz + 1] - 'a'] = new Trie;

    adauga(nod->fiu[cuv[poz + 1] - 'a'], poz + 1, careCuv);
}

void getFail()
{
    queue <Trie*> Q;
    for (int i = 0; i < 26; i++)
        if (T->fiu[i])
        {
            T->fiu[i]->fail = T;
            Q.push(T->fiu[i]);
        }

    while (!Q.empty())
    {
        Trie *nod = Q.front(); // ii fac fiii lui nod
        Q.pop();

        for (int i = 0; i < 26; i++)
            if (nod->fiu[i])
            {
                Trie *f = nod->fail;
                while (f != T && f->fiu[i] == 0)
                    f = f->fail;

                if (f->fiu[i])
                    f = f->fiu[i];

                nod->fiu[i]->fail = f;

                Q.push(nod->fiu[i]);
            }
    }
}

int main()
{
    cin >> A + 1;
    n = strlen(A + 1);

    cin >> m;
    for (int i = 1; i <= m; i++)
    {
        cin >> cuv + 1;
        adauga(T, 0, i);
    }

    getFail();



    Trie *curr = T;
    for (int i = 1; i <= n; i++)
    {
        char c = A[i] - 'a';
        if (curr->fiu[c])
        {
            curr = curr->fiu[c];
        }
        else
        {
            while (curr != T && curr->fiu[c] == 0)
                curr = curr->fail;

            if (curr->fiu[c])
                curr = curr->fiu[c];
        }

        curr->rezNod++;
    }

    vector <Trie*> toateNodurile;
    toateNodurile.push_back(T);
    for (int i = 0; i < toateNodurile.size(); i++)
    {
        Trie *curr = toateNodurile[i];
        for (int j = 0; j < 26; j++)
            if (curr->fiu[j])
                toateNodurile.push_back(curr->fiu[j]);
    }

    reverse(toateNodurile.begin(), toateNodurile.end());

    for (auto curr: toateNodurile)
    {
        if (curr->fail)
            curr->fail->rezNod += curr->rezNod;
        for (auto x: curr->ceCuv)
            ans[x] = curr->rezNod;
    }



    for (int i = 1; i <= m; i++)
        cout << ans[i] << "\n";


    return 0;
}