Cod sursa(job #2674417)

Utilizator BAlexandruBorgovan Alexandru BAlexandru Data 19 noiembrie 2020 09:21:12
Problema Aho-Corasick Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.88 kb
#include <fstream>
#include <queue>

using namespace std;

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

struct trieNode
{
    bool isEndOfWord;
    int word;

    char c;

    trieNode* suffix;
    trieNode* dictionarySuffix;

    trieNode* parent;
    trieNode* children[26];

    trieNode(trieNode* Parent, char ch)
    {
        isEndOfWord = false;

        c = ch;

        suffix = NULL;
        dictionarySuffix = NULL;

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

class trie
{
    private:
        int N;

        int ans[101];

        trieNode* root = new trieNode(NULL, 0);

        queue < trieNode* > q;

        void insertKey(string key, int ind);

    public:
        void insertKeys(string keys[101], int n);
        void getSuffixes();
        void getDictionarySuffixes();
        void query(string &text);

};

void trie :: insertKey(string key, int ind)
{
    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, key[i]);

        node = node -> children[index];
    }

    node -> isEndOfWord = true;
    node -> word = ind;
}

void trie :: insertKeys(string keys[101], int n)
{
    N = n;
    for (int i=1; i<=n; i++)
        insertKey(keys[i], i);
}

void trie :: getSuffixes()
{
    q.push(root);

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

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

        if (node == root)
            continue;

        if (node -> parent == root)
        {
            node -> suffix = root;
            continue;
        }

        trieNode* p = node -> parent -> suffix;
        int index = node -> c - 'a';

        while (p != root && !p -> children[index])
            p = p -> suffix;

        if (p -> children[index] && p != node -> parent)
            node -> suffix = p -> children[index];
        else
            node -> suffix = NULL;
    }
}

void trie :: getDictionarySuffixes()
{
    q.push(root);

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

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

        if (node == root)
            continue;

        if (node -> parent == root)
            continue;

        trieNode* p = node -> suffix;
        while (p && !p -> isEndOfWord)
            p = p -> suffix;

        if (p && p -> isEndOfWord)
            node -> dictionarySuffix = p;
    }
}

void trie :: query(string &text)
{
    int n = text.size();
    trieNode* node = root;

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

        if (node -> children[index])
            node = node -> children[index];
        else
        {
            trieNode* p = node -> suffix;
            while (p && !p -> children[index])
                p = p -> suffix;

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

        ans[node -> word] += node -> isEndOfWord;

        trieNode *aux = node;
        while (aux -> dictionarySuffix)
        {
            aux = aux -> dictionarySuffix;
            ans[aux -> word]++;
        }
    }

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

int n;
string text;
string pattern[101];

trie t;

int main()
{
    f >> text;

    f >> n;
    for (int i=1; i<=n; i++)
        f >> pattern[i];

    t.insertKeys(pattern, n);
    t.getSuffixes();
    t.getDictionarySuffixes();

    t.query(text);

    return 0;
}