Cod sursa(job #995665)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 10 septembrie 2013 01:02:40
Problema Substr Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.87 kb
#include <fstream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>

using namespace std;

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

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

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

    SuffixAutomaton(const string word = "") {
        nodes.push_back(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 GetLongestKMatches(const int k) const {
        int length = 0;
        for (int x = 0; x < int(nodes.size()); ++x)
            if (nodes[x].endings >= k)
                length = max(length, nodes[x].length);
        return length;
    }

  private:
    int lastNode;
    vector<Node> nodes;

    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;
    }

    int GetEndings(const int x) {
        if (nodes[x].solved)
            return nodes[x].endings;
        for (const auto &y: nodes[x].edges)
            nodes[x].endings += GetEndings(y.second);
        nodes[x].solved = true;
        return nodes[x].endings;
    }
};

string S;
int K, Solution;

void Solve() {
    SuffixAutomaton T = SuffixAutomaton(S);
    T.Preprocess();
    Solution = T.GetLongestKMatches(K);
}

void Read() {
    ifstream cin("substr.in");
    int n;
    cin >> n >> K >> S;
    cin.close();
}

void Print() {
    ofstream cout("substr.out");
    cout << Solution << "\n";
    cout.close();
}

int main() {
    Read();
    Solve();
    Print();
    return 0;
}