Cod sursa(job #2676485)

Utilizator BAlexandruBorgovan Alexandru BAlexandru Data 24 noiembrie 2020 14:36:55
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.35 kb
#include <fstream>
#include <vector>
#include <queue>

using namespace std;

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

struct trieNode
{
    int Count;

    vector < int > words;

    trieNode* suffixLink;
    trieNode* children[26];

    trieNode()
    {
        Count = 0;

        suffixLink = NULL;

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

class trie
{
    int N = 0;
    int ans[101];

    trieNode* root = new trieNode();

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

void trie :: insertKey(string &key)
{
    N++;

    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];
    }

    node -> words.push_back(N);
}

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

    for (int i=0; i<26; 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<26; 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(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 -> Count++;
    }

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

    q.push(root);

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

        antibfs.push_back(node);

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

    int imax = antibfs.size() - 1;
    for (int i=imax; i>=0; i--)
    {
        trieNode* node = antibfs[i];

        for (auto word : node -> words)
            ans[word] = node -> Count;

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

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

int n;

string text, pattern;

trie T;

int main()
{
    f >> text;

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

    T.computeSuffixLinks();

    T.query(text);

    return 0;
}