Pagini recente » Cod sursa (job #1486421) | Cod sursa (job #622538) | Cod sursa (job #446767) | Cod sursa (job #1450748) | Cod sursa (job #1856766)
#include <fstream>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
ifstream cin ("substr.in");
ofstream cout ("substr.out");
const int MaxN = 16500, MaxLog = 15, HashMod1 = 666013, HashMod2 = 733333, HashBase = 73;
string str;
int n, k, globalAns;
int suffixArray[MaxLog][MaxN], Log[MaxN], H1[HashMod1 + 5], H2[HashMod2 + 5];
class StrSeg {
public:
int lfCode, rgCode, pos;
inline bool operator < (const StrSeg &other) const {
if (lfCode == other.lfCode) {
return rgCode < other.rgCode;
}
return lfCode < other.lfCode;
}
};
StrSeg segOf[MaxN];
void InitSuffixArray() {
for (int i = 0; i < n; ++i) {
suffixArray[0][i] = str[i] + 1;
}
for (int step = 1; step <= Log[n]; ++step) {
int prevLng = (1 << (step - 1));
for (int i = 0; i < n; ++i) {
segOf[i].lfCode = suffixArray[step - 1][i];
segOf[i].rgCode = (i + prevLng < n) ? suffixArray[step - 1][i + prevLng] : 0;
segOf[i].pos = i;
}
stable_sort(&segOf[0], &segOf[n]);
int segTop = 0;
suffixArray[step][segOf[0].pos] = ++segTop;
for (int i = 1; i < n; ++i) {
if (segOf[i].lfCode != segOf[i - 1].lfCode or segOf[i].rgCode != segOf[i - 1].rgCode) {
++segTop;
}
suffixArray[step][segOf[i].pos] = segTop;
}
}
}
void LCP(int index1, int index2, int length) {
int pos1 = segOf[index1].pos;
int pos2 = segOf[index2].pos;
int Hash1 = 0;
int Hash2 = 0;
int lngLCP = 0;
for (int step = Log[length]; step >= 0; --step) {
int currLng = (1 << step);
if (suffixArray[step][pos1] and lngLCP + currLng <= length and suffixArray[step][pos1] == suffixArray[step][pos2]) {
Hash1 = ((1LL * Hash1 * HashBase) + suffixArray[step][pos1]) % HashMod1;
Hash2 = ((1LL * Hash2 * HashBase) + suffixArray[step][pos2]) % HashMod2;
pos1 += currLng;
pos2 += currLng;
lngLCP += currLng;
}
}
if (lngLCP == length) {
H1[Hash1] += 1 + (H1[Hash1] == 0);
H2[Hash2] += 1 + (H2[Hash2] == 0);
}
}
bool Check(int length) {
memset(H1, 0, sizeof H1);
memset(H2, 0, sizeof H2);
for (int i = 1; i < n; ++i) {
LCP(i, i - 1, length);
}
bool ok1 = false;
bool ok2 = false;
for (int i = 0; i < HashMod2; ++i) {
if (H2[i] >= k) {
ok2 = true;
}
if (i < HashMod1 and H1[i] >= k) {
ok1 = true;
}
}
return ok1 and ok2;
}
int BinSearch(int lf = 1, int rg = n) {
int ans = 0;
while (lf <= rg) {
int med = (lf + rg) / 2;
if (Check(med)) {
lf = med + 1;
ans = med;
}
else {
rg = med - 1;
}
}
return ans;
}
int main() {
cin >> n >> k >> str;
for (int i = 2; i < MaxN; ++i) {
Log[i] = Log[i / 2] + 1;
}
InitSuffixArray();
globalAns = BinSearch();
cout << globalAns << '\n';
return 0;
}