Cod sursa(job #1053488)

Utilizator ELHoriaHoria Cretescu ELHoria Data 12 decembrie 2013 19:43:59
Problema Substr Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.58 kb
#include <fstream>
#include <map>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

ifstream cin("substr.in");
ofstream cout("substr.out");


string str;
int N, K;
vector<int> S[1 << 15];
int num;

class SuffixAutomaton {
public:

	SuffixAutomaton(const string &data = "") {
		state.resize(data.size() << 1);
		state[0].length = 0;
		state[0].link = -1;
		size = 1;
		last = 0;
		int i = 0;
		for (const char &c : data) {
			extend(c, i);
		}
	}

	void df(int v, int lg) {
		for (const auto w : state[v].next) {
			df(w.second, lg + 1);
		}
		
		if (v) {
			S[lg].push_back(v);
		}
	}

	int count(int v) {
		if (v) {
			num = 0;
			getAllOccurences(v, state[v].length);
			return num; 
		}

		return 0;
	}

	void getAllOccurences(int v, int lg) {
		if (!state[v].isClone)
			num++;

		for (auto &link : state[v].inverseLinks) {
			getAllOccurences(link, lg);
		}

	}

	void compute() {
		for (int i = 1; i < size; i++) {
			state[state[i].link].inverseLinks.push_back(i);
		}
	}

private:
	struct State {
		int length;
		int link;
		int firstPos;
		vector<int> inverseLinks;
		map<char, int> next;
		bool isClone;
		State() : length(0), link(-1), isClone(false), firstPos(0) {}
	};

	vector< State > state;
	int size, last;

	void extend(char c, int &index) {
		int current = size++;
		state[current].length = state[last].length + 1;
		state[current].firstPos = index++;
		int p;
		for (p = last; p != -1 && !state[p].next.count(c); p = state[p].link) {
			state[p].next[c] = current;
		}

		if (p == -1) {
			state[current].link = 0;
		}
		else {
			int q = state[p].next[c];
			if (state[p].length + 1 == state[q].length) {
				state[current].link = q;
			}
			else {
				int clone = size++;
				state[clone].link = state[q].link;
				state[clone].next = state[q].next;
				state[clone].length = state[p].length + 1;
				state[clone].isClone = true;
				for (; p != -1 && state[p].next[c] == q; p = state[p].link) {
					state[p].next[c] = clone;
				}
				state[q].link = state[current].link = clone;
			}
		}
		last = current;
	}
};

bool isGood(int lg, SuffixAutomaton &sa) {
	for (const int &state : S[lg]) {
		if (sa.count(state) >= K) {
			return true;
		}
	}
	return false;
}

int main()
{
	cin >> N >> K;
	cin.get();
	getline(cin, str);
	SuffixAutomaton sa(str);
	sa.compute();
	sa.df(0, 0);
	int ans = 0;
	for (int step = 1 << 15; step > 0; step >>= 1) {
		if (step + ans <= N && isGood(step + ans,sa)) {
			ans += step;
		}
	}

	cout << ans << "\n";
	return 0;
}