Cod sursa(job #2305262)

Utilizator dacianouaPapadia Mortala dacianoua Data 19 decembrie 2018 19:11:48
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.15 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;
}