Cod sursa(job #1165098)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 2 aprilie 2014 14:22:43
Problema Aho-Corasick Scor 25
Compilator cpp Status done
Runda Arhiva educationala Marime 2.9 kb
#include <fstream>
#include <vector>
#include <map>

using namespace std;

class SuffixAutomaton {
  public:
    SuffixAutomaton(const string &word = ""):
      nodes(vector<Node>(1, Node())),
      lastNode(0) {
        for (int i = 0; i < int(word.length()); ++i)
            Extend(word[i]);
    }

    void Preprocess() {
        for (int x = lastNode; x != Node::NIL; x = nodes[x].link)
            nodes[x].endings = 1;
        GetEndings(0);
    }

    int GetFrequence(const string &pattern) {
        int x = 0;
        for (int i = 0; i < int(pattern.length()); ++i) {
            if (nodes[x].edges.count(pattern[i]) == 0)
                return 0;
            x = nodes[x].edges[pattern[i]];
        }
        return nodes[x].endings;
    }

  private:
    class Node {
      public:
        static const int NIL = -1;

        int length, link;
        map<char, int> edges;
        int endings;
        bool solved;

        Node(const int _length = 0, const int _link = NIL):
          length(_length),
          link(_link),
          edges(map<char, int>()),
          endings(0),
          solved(false) {}
    };

    vector<Node> nodes;
    int lastNode;

    void Extend(const char symbol) {
        int current = int(nodes.size());
        nodes.push_back(Node(nodes[lastNode].length + 1));
        int x = lastNode;
        for (; x != Node::NIL && nodes[x].edges.count(symbol) == 0; x = nodes[x].link)
            nodes[x].edges[symbol] = current;
        lastNode = current;
        if (x == Node::NIL) {
            nodes[current].link = 0;
            return;
        }
        int next = nodes[x].edges[symbol];
        if (nodes[x].length + 1 == nodes[next].length) {
            nodes[current].link = next;
            return;
        }
        int clone = int(nodes.size());
        nodes.push_back(Node(nodes[x].length + 1, nodes[next].link));
        nodes[clone].edges = nodes[next].edges;
        for (; x != Node::NIL && nodes[x].edges[symbol] == next; x = nodes[x].link)
            nodes[x].edges[symbol] = clone;
        nodes[current].link = nodes[next].link = clone;
    }

    void GetEndings(const int x) {
        nodes[x].solved = true;
        for (map<char, int>::const_iterator e = nodes[x].edges.begin(); e != nodes[x].edges.end(); ++e) {
            if (!nodes[e->second].solved)
                GetEndings(e->second);
            nodes[x].endings += nodes[e->second].endings;
        }
    }
};

int main() {
    ifstream cin("ahocorasick.in");
    ofstream cout("ahocorasick.out");
    string word;
    cin >> word;
    SuffixAutomaton automaton = SuffixAutomaton(word);
    automaton.Preprocess();
    int q;
    cin >> q;
    for (; q > 0; --q) {
        string pattern;
        cin >> pattern;
        cout << automaton.GetFrequence(pattern) << "\n";
    }
    cin.close();
    cout.close();
    return 0;
}