Pagini recente » Cod sursa (job #460889) | Cod sursa (job #753488) | Cod sursa (job #1391462) | Cod sursa (job #1966217) | Cod sursa (job #1053488)
#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;
}