Cod sursa(job #1204883)

Utilizator andreiiiiPopa Andrei andreiiii Data 4 iulie 2014 12:48:18
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.68 kb
#include <algorithm>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

class AhoCorasick {
public:
    AhoCorasick():
        Nodes(vector<AhoCorasickNode>(1)),
        BfsOrder(vector<int>()),
        CountWords(0) {}

    void insert(const string &S)
    {
        int node = 0;
        for (int i = 0; i < int(S.size()); i++)
        {
            if (!Nodes[node].links[S[i] - 'a'])
            {
                Nodes[node].links[S[i] - 'a'] = Nodes.size();
                Nodes.push_back(AhoCorasickNode());
            }
            node = Nodes[node].links[S[i] - 'a'];
        }
        Nodes[node].words.push_back(CountWords++);
    }

    void build()
    {
        BfsOrder.push_back(0);
        for (int i = 0; i < int(BfsOrder.size()); i++)
        {
            const int node = BfsOrder[i];

            for (int j = 0; j < 26; j++)
            {
                if (!Nodes[node].links[j]) continue;

                int k;
                for (k = Nodes[node].fail; !Nodes[k].links[j] && k; k = Nodes[k].fail);

                if (Nodes[k].links[j] && Nodes[k].links[j] != Nodes[node].links[j]) k = Nodes[k].links[j];
                Nodes[Nodes[node].links[j]].fail = k;

                BfsOrder.push_back(Nodes[node].links[j]);
            }
        }
    }

    vector<int> getFreqs(const string &S)
    {
        vector<int> Frequences = vector<int>(CountWords, 0);

        for (int i = 0, node = 0; i < int(S.size()); i++)
        {
            for (; !Nodes[node].links[S[i] - 'a'] && node; node = Nodes[node].fail);
            if (Nodes[node].links[S[i] - 'a']) node = Nodes[node].links[S[i] - 'a'];

            Nodes[node].count++;
        }

        for (int i = BfsOrder.size() - 1; i >= 0; i--)
        {
            const int node = BfsOrder[i];

            Nodes[Nodes[node].fail].count += Nodes[node].count;
            for (const int p: Nodes[node].words) Frequences[p] = Nodes[node].count;
        }

        return Frequences;
    }
private:
    class AhoCorasickNode {
    public:
        int count, fail;
        int links[26];
        vector<int> words;

        AhoCorasickNode():
            count(0),
            fail(0),
            links{0},
            words(vector<int>()){}
    };

    vector<AhoCorasickNode> Nodes;
    vector<int> BfsOrder;
    int CountWords;
};

string S;

int main()
{
    ifstream cin("ahocorasick.in");
    ofstream cout("ahocorasick.out");

    cin >> S;

    int T;
    cin >> T;

    AhoCorasick A;
    while (T--)
    {
        string Word;
        cin >> Word;

        A.insert(Word);
    }

    A.build();

    vector<int> Freq = A.getFreqs(S);
    for(const int p: Freq) cout << p << "\n";

    cin.close();
    cout.close();
}