Cod sursa(job #3239458)

Utilizator _andrei4567Stan Andrei _andrei4567 Data 5 august 2024 17:48:56
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.26 kb
#include <fstream>
#include <queue>
#include <algorithm>

using namespace std;

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

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

bool viz[M + 1];
int val[M + 1];

vector <int> g[M + 1], v;

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;

queue <trie*> pq;

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 dfs (trie *root)
{
    for (int i = 0; i < 26; ++i)
        if (root->children[i] != nullptr)
        {
            dfs (root->children[i]);
        }
    if (root->suff_link != nullptr)
        g[root->nr].push_back(root->suff_link->nr);
}

void dfs1 (int node)
{
    viz[node] = 1;
    for (auto it : g[node])
        if (!viz[it])
        dfs1 (it);
    v.push_back(node);
}

void dfs2 (trie *root)
{
    if (root->isleaf)
    {
        for (auto it : root->index)
            rez[it] = val[root->nr];
    }
    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, val[root->nr]++;
        else
            root = suff(root, ch), root->dp += 1, val[root->nr]++;
    }
}

int 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);
    for (int i = 1; i <= t; ++i)
        if (!viz[i])
            dfs1(i);
    reverse (v.begin(), v.end());
    for (auto it : v)
        for (auto it1 : g[it])
            val[it1] += val[it];
    dfs2 (root);
    for (int i = 1; i <= n; ++i)
        cout << rez[i] << '\n';
    return 0;
}