Cod sursa(job #2877689)

Utilizator alexmorosanuMorosanu Alexandru alexmorosanu Data 25 martie 2022 11:01:27
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4 kb
#include <bits/stdc++.h>
using namespace std;
ifstream f("ahocorasick.in");
ofstream g("ahocorasick.out");
struct aho
{
    int letter, cnt;
    aho *next[26], *par, *fail, *exit;
    vector<int> leafs;
    // string ss;
    aho()
    {
        letter = cnt = 0;
        for (int i = 0; i < 26; i++)
            next[i] = nullptr;
        par = fail = exit = nullptr;
        leafs.clear();
    }
} *root = new aho;
struct box
{
    aho *x;
    box(aho *i) { x = i; }
};
string text;
int n, af[102];
vector<string> v;
void adauga(const string &, int);
void prepare_aho();
void process_text();
void get_results();
// void print_aho();
int32_t main()
{
    f >> text >> n;
    root->par = root;
    for (int i = 1; i <= n; i++)
    {
        static string s;
        f >> s;
        adauga(s, i);
    }
    prepare_aho();
    process_text();
    get_results();
    for (int i = 1; i <= n; i++)
        g << af[i] << '\n';
    return 0;
}
// void print_aho()
// {
//     queue<box> q;
//     q.push(box(root));
//     while (!q.empty())
//     {
//         aho *ax = q.front().x;
//         q.pop();
//         g << ax->ss << " " << ax->fail->ss << '\n';
//         for (int i = 0; i < 26; i++)
//             if (ax->next[i] != nullptr)
//                 q.push(ax->next[i]);
//     }
// }
void adauga(const string &s, int x)
{
    aho *ax = root;

    for (const char &ch : s)
    {
        if (ax->next[ch - 'a'] == nullptr)
        {
            ax->next[ch - 'a'] = new aho;
            ax->next[ch - 'a']->letter = ch - 'a';
        }
        ax->next[ch - 'a']->par = ax;
        ax = ax->next[ch - 'a'];
        // ax->ss = ax->par->ss + ch;
    }
    ax->leafs.push_back(x);
}
void prepare_aho()
{
    queue<box> q;
    q.push(box(root));
    while (!q.empty())
    {
        aho *ax = q.front().x;
        q.pop();
        if (ax == root)
            ax->fail = ax->exit = root;
        else if (ax->par == root)
        {
            ax->fail = root;
            if (!ax->leafs.empty())
                ax->exit = ax;
            else
                ax->exit = root;
        }
        else
        {
            aho *j = ax->par->fail;
            while (true)
            {
                if (j->next[ax->letter] != nullptr)
                {
                    ax->fail = j->next[ax->letter];
                    break;
                }
                if (j == root)
                {
                    ax->fail = root;
                    break;
                }
                j = j->fail;
            }
            if (!ax->leafs.empty())
                ax->exit = ax;
            else
                ax->exit = ax->fail->exit;
        }
        for (int i = 0; i < 26; i++)
            if (ax->next[i] != nullptr)
                q.push(box(ax->next[i]));
    }
}
void process_text()
{
    aho *ax = root;
    for (const char &ch : text)
    {
        while (true)
        {
            if (ax->next[ch - 'a'] != nullptr)
            {
                ax = ax->next[ch - 'a'];
                break;
            }
            if (ax == root)
                break;
            ax = ax->fail;
        }
        ax->cnt++;
        // aho *cr = ax;
        // while (true)
        // {
        //     cr = cr->exit;
        //     if (cr == root)
        //         break;
        //     for (const int &i : cr->leafs)
        //         af[i]++;
        //     cr = cr->fail;
        // }
    }
}
void get_results()
{
    queue<box> q;
    stack<box> st;
    q.push(box(root));
    while (!q.empty())
    {
        aho *ax = q.front().x;
        st.push(q.front());
        q.pop();
        for (int i = 0; i < 26; i++)
            if (ax->next[i] != nullptr)
                q.push(box(ax->next[i]));
    }
    while (!st.empty())
    {
        aho *ax = st.top().x;
        st.pop();
        for (const int &i : ax->leafs)
            af[i] += ax->cnt;
        ax->fail->cnt += ax->cnt;
    }
}