Cod sursa(job #2877732)

Utilizator BAlexandruBorgovan Alexandru BAlexandru Data 25 martie 2022 11:52:47
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.96 kb
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

ifstream f("ahocorasick.in");
ofstream g("ahocorasick.out");

const int SIGMA = 26;

class trie
{
    private:
        struct trieNode
        {
            int cnt;

            vector < int > words;

            trieNode* suffixLink;
            trieNode* children[SIGMA];

            trieNode();
        };

        trieNode* root;

        int numberOfWords;

        void clearTrie(trieNode*& node);

    public:
        trie();
        ~trie();
        void insertKey(const string& key);
        void computeSuffixLinks();
        void query(const string& text);
};

trie :: trieNode :: trieNode()
{
    cnt = 0;

    suffixLink = NULL;

    for (int i = 0; i < SIGMA; i++)
        children[i] = NULL;
}

void trie :: clearTrie(trieNode*& node)
{
    for (int i = 0; i < SIGMA; i++)
        if (node -> children[i])
            clearTrie(node -> children[i]);

    delete node;
}

trie :: trie()
{
    numberOfWords = 0;
    root = new trieNode;
}

trie :: ~trie()
{
    clearTrie(root);
}

void trie :: insertKey(const string& key)
{
    trieNode* node = root;

    for (int i = 0; i < key.size(); i++)
    {
        int index = key[i] - 'a';

        if (!node -> children[index])
            node -> children[index] = new trieNode;

        node = node -> children[index];
    }

    numberOfWords++;
    node -> words.push_back(numberOfWords);
}

void trie :: computeSuffixLinks()
{
    queue < trieNode* > q;

    for (int i = 0; i < SIGMA; i++)
        if (root -> children[i])
        {
            root -> children[i] -> suffixLink = root;
            q.push(root -> children[i]);
        }

    while (!q.empty())
    {
        trieNode* node = q.front();
        q.pop();

        for (int i = 0; i < SIGMA; i++)
            if (node -> children[i])
            {
                trieNode* aux = node -> suffixLink;

                while (aux && !aux -> children[i])
                    aux = aux -> suffixLink;

                if (aux && aux -> children[i])
                    node -> children[i] -> suffixLink = aux -> children[i];
                else
                    node -> children[i] -> suffixLink = root;

                q.push(node -> children[i]);
            }
    }
}

void trie :: query(const string& text)
{
    trieNode* node = root;

    for (int i = 0; i < text.size(); i++)
    {
        int index = text[i] - 'a';

        if (node -> children[index])
            node = node -> children[index];
        else
        {
            trieNode* aux = node -> suffixLink;

            while (aux && !aux -> children[index])
                aux = aux -> suffixLink;

            if (aux && aux -> children[index])
                node = aux -> children[index];
            else
                node = root;
        }

        node -> cnt++;
    }

    queue < trieNode* > q;
    vector < trieNode* > antibfs;

    q.push(root);

    while (!q.empty())
    {
        trieNode* node = q.front();
        q.pop();

        antibfs.push_back(node);

        for (int i = 0; i < SIGMA; i++)
            if (node -> children[i])
                q.push(node -> children[i]);
    }

    int* ans = new int[numberOfWords + 1];

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

    for (auto node : antibfs)
    {
        for (auto word : node -> words)
            ans[word] = node -> cnt;

        if (node -> suffixLink)
            node -> suffixLink -> cnt += node -> cnt;
    }

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

    delete[] ans;
}

int n;

string text;

trie T;

int main()
{
    f >> text;

    f >> n;

    for (int i = 1; i <= n; i++)
    {
        string word; f >> word;
        T.insertKey(word);
    }

    T.computeSuffixLinks();

    T.query(text);

    return 0;
}