Cod sursa(job #2082835)

Utilizator radarobertRada Robert Gabriel radarobert Data 6 decembrie 2017 20:31:00
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.22 kb
#include <fstream>
#include <list>
#include <cstring>
#include <queue>
#include <iostream>

using namespace std;

const int ALPHABET_SIZE = 26;

class Node
{
public:

    Node *fail;
    Node *next[ALPHABET_SIZE];
    list<int> out;
    int counter;

    Node()
    {
        counter = 0;
        fail = nullptr;
        for (int i = 0; i < ALPHABET_SIZE; i++)
            next[i] = nullptr;
    }
};

void addWord(Node *root, string &word, int index)
{
    Node *node = root;

    for (int i = 0; i < word.size(); i++)
    {
        if (node->next[word[i] - 'a'] == nullptr)
            node->next[word[i] - 'a'] = new Node();

        node = node->next[word[i] - 'a'];
    }

    node->out.push_back(index);
}

void buildFailLinks(Node *root)
{
    queue<Node*> q;

    root->fail = root;
    for (int i = 0; i < ALPHABET_SIZE; i++)
        if (root->next[i] != nullptr)
        {
            root->next[i]->fail = root;
            q.push(root->next[i]);
        }

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

        for (int i = 0; i < ALPHABET_SIZE; i++)
        {
            if (node->next[i] == nullptr)
                continue;

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

            Node *f = node->fail;
            while (f->next[i] == nullptr && f != root)
                f = f->fail;

            if (f->next[i] == nullptr)
            {
                node->next[i]->fail = root;
                continue;
            }

            node->next[i]->fail = f->next[i];
            for (auto &it: f->next[i]->out)
                node->next[i]->out.push_back(it);
        }
    }
}

void solve(string &text, vector<string> &dictionary)
{
    int *counter = new int[dictionary.size()];
    for (int i = 0; i < dictionary.size(); i++)
        counter[i] = 0;

    Node *root = new Node();

    for (int i = 0; i < dictionary.size(); i++)
        addWord(root, dictionary[i], i);

    buildFailLinks(root);

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

        while (node->next[index] == nullptr && node != root)
            node = node->fail;

        if (node->next[index] == nullptr)
            continue;

        node = node->next[index];
        node->counter++;
    }

    queue<Node*> q;
    q.push(root);

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

        for (const auto &it: node->out)
            counter[it] += node->counter;

        for (int i = 0; i < ALPHABET_SIZE; i++)
            if (node->next[i] != nullptr)
            {
                q.push(node->next[i]);
            }
    }

    ofstream out("ahocorasick.out");
    for (int i = 0; i < dictionary.size(); i++)
        out << counter[i] << '\n';
}

int main()
{
    ifstream in("ahocorasick.in");
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    string text;
    in >> text;

    int n;
    in >> n;
    vector<string> dictionary;

    for (int i = 0; i < n; i++)
    {
        string word;
        in >> word;
        dictionary.push_back(word);
    }

    solve(text, dictionary);

    return 0;
}