Cod sursa(job #1268930)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 21 noiembrie 2014 17:51:40
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.48 kb
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

class AhoCorasickAutomaton {
  public:
    static const int SIGMA = 26;
    static const int NIL;// = -1;

    AhoCorasickAutomaton(const vector<string> signatures):
      size(1),
      start(0),
      delta(vector< vector<int> >(1, vector<int>(SIGMA, NIL))),
      pi(vector<int>(1, NIL)),
      order(vector<int>()),
      signatureCount(int(signatures.size())),
      signatureIndices(vector< vector<int> >(1, vector<int>())) {
        for (int i = 0; i < int(signatures.size()); ++i) {
            int x = start;
            for (int j = 0; j < int(signatures[i].length()); x = delta[x][Encode(signatures[i][j++])])
                if (delta[x][Encode(signatures[i][j])] == NIL)
                    delta[x][Encode(signatures[i][j])] = NewNode();
            signatureIndices[x].push_back(i);
        }
        order.push_back(start);
        pi[start] = start;
        for (int i = 0; i < int(order.size()); ++i) {
            int x = order[i];
            for (int symbol = 0; symbol < SIGMA; ++symbol) {
                int p = pi[x];
                for (; p != start && delta[p][symbol] == NIL; p = pi[p]);
                if (delta[p][symbol] != NIL && delta[p][symbol] != delta[x][symbol])
                    p = delta[p][symbol];
                if (delta[x][symbol] != NIL) {
                    pi[delta[x][symbol]] = p;
                    order.push_back(delta[x][symbol]);
                } else {
                    delta[x][symbol] = p;
                }
            }
        }
        reverse(order.begin(), order.end());
    }

    vector<int> GetFrequences(const string &stringToSearch) const {
        vector<int> nodeFrequences = vector<int>(size, 0), signatureFrequences = vector<int>(signatureCount, 0);
        for (int i = 0, x = start; i < int(stringToSearch.length()); ++i)
            ++nodeFrequences[x = delta[x][Encode(stringToSearch[i])]];
        for (vector<int>::const_iterator x = order.begin(); x != order.end(); ++x)
            if (*x != start)
                nodeFrequences[pi[*x]] += nodeFrequences[*x];
        for (int x = 0; x < size; ++x)
            if (x != start)
                for (vector<int>::const_iterator s = signatureIndices[x].begin(); s != signatureIndices[x].end(); ++s)
                    signatureFrequences[*s] += nodeFrequences[x];
        return signatureFrequences;
    }

  private:
    int size, start;
    vector< vector<int> > delta;
    vector<int> pi, order;
    int signatureCount;
    vector< vector<int> > signatureIndices;

    static int Encode(const char symbol) {
        return int(symbol - 'a');
    }

    int NewNode() {
        delta.push_back(vector<int>(SIGMA, NIL));
        pi.push_back(NIL);
        signatureIndices.push_back(vector<int>());
        return size++;
    }
};

const int AhoCorasickAutomaton::NIL = -1;

int main() {
    ifstream cin("ahocorasick.in");
    ofstream cout("ahocorasick.out");
    string stringToSearch;
    cin >> stringToSearch;
    int n;
    cin >> n;
    vector<string> signatures = vector<string>(n, "");
    for (int i = 0; i < n; ++i)
        cin >> signatures[i];
    AhoCorasickAutomaton A = AhoCorasickAutomaton(signatures);
    vector<int> frequences = A.GetFrequences(stringToSearch);
    for (int i = 0; i < int(frequences.size()); ++i)
        cout << frequences[i] << "\n";
    cin.close();
    cout.close();
    return 0;
}