Cod sursa(job #3239446)

Utilizator _andrei4567Stan Andrei _andrei4567 Data 5 august 2024 16:53:20
Problema Aho-Corasick Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.18 kb
#include <fstream>
#include <queue>
#define int long long

using namespace std;

ifstream cin ("ahocorasick.in");
ofstream cout ("ahocorasick.out");

const int M = 1e6;
const int N = 100;
int rez[N + 1];

bool f[M + 1];

struct trie
{
    int dp, nr;
    vector <int> index;
    bool isleaf;
    trie *children[26], *suff_link;
    trie (int x = 0)
    {
        dp = 0;
        nr = x;
        index.clear();
        isleaf = false;
        suff_link = nullptr;
        for (int i = 0; i < 26; ++i)
            children[i] = nullptr;
    }
};

trie *root = new trie();

string a, s;

int n, poz, t;

void add_word (trie *root, string s)
{
    for (auto it : s)
    {
        int ch = it - 'a';
        if (root->children[ch] == nullptr)
            root->children[ch] = new trie(++t);
        root = root->children[ch];
    }
    root->isleaf = 1;
    root->index.push_back(poz);
}

trie* suff (trie *aux, int poz)
{
    if (aux == root && aux->children[poz] != nullptr)
        return aux->children[poz];
    while (aux != root)
    {
        aux = aux->suff_link;
        if (aux->children[poz] != nullptr)
            return aux->children[poz];
    }
    return aux;
}

void bfs (trie *root)
{
    queue <trie*> q;
    for (int i = 0; i < 26; ++i)
        if (root->children[i] != nullptr)
            root->children[i]->suff_link = root, q.push(root->children[i]);
    while (!q.empty())
    {
        trie *aux = q.front();
        q.pop();
        for (int i = 0; i < 26; ++i)
            if (aux->children[i] != nullptr)
            {
                aux->children[i]->suff_link = suff(aux, i);
                q.push(aux->children[i]);
            }
    }

}

void go_up (trie *root)
{
    while (root->suff_link != nullptr)
    {
        if (root->nr == 1);
        root->suff_link->dp += root->dp;
        root = root->suff_link;
    }
}

void dfs (trie *root)
{
    for (int i = 0; i < 26; ++i)
        if (root->children[i] != nullptr)
            dfs (root->children[i]);
    if (root->suff_link != nullptr)
        f[root->suff_link->nr] = 1;
}

void dfs1 (trie *root)
{
    for (int i = 0; i < 26; ++i)
        if (root->children[i] != nullptr)
            dfs1 (root->children[i]);
    if (!f[root->nr])
        go_up(root);
}

void dfs2 (trie *root)
{
    if (root->isleaf)
    {
        for (auto it : root->index)
            rez[it] = root->dp;
    }
    for (int i = 0; i < 26; ++i)
        if (root->children[i] != nullptr)
            dfs2 (root->children[i]);
}

void solve (trie *root)
{
    for (auto it : s)
    {
        int ch = it - 'a';
        if (root->children[ch] != nullptr)
            root = root->children[ch], root->dp += 1;
        else
            root = suff(root, ch), root->dp += 1;
    }
}

signed main()
{
    ios_base :: sync_with_stdio(false);
    cin.tie(0);
    cin >> s >> n;
    for (int i = 1; i <= n; ++i)
    {
        cin >> a;
        ++poz;
        add_word(root, a);
    }
    bfs(root);
    solve(root);
    dfs (root);
    dfs1 (root);
    dfs2 (root);
    for (int i = 1; i <= n; ++i)
        cout << rez[i] << '\n';
    return 0;
}