Pagini recente » Cod sursa (job #2222028) | Cod sursa (job #2268524) | Cod sursa (job #422630) | Cod sursa (job #1796959) | Cod sursa (job #1858303)
#include <fstream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <deque>
using namespace std;
ifstream cin ("substr.in");
ofstream cout ("substr.out");
const int MaxN = 16500, MaxLog = 15;
string str;
deque <int> Dq;
vector <int> LCPList;
int n, k, globalAns;
int suffixArray[MaxLog][MaxN], Log[MaxN], posOf[MaxN];
class StrSeg {
public:
int lfCode, rgCode, pos;
bool operator < (const StrSeg &other) const {
if (lfCode == other.lfCode) {
return rgCode < other.rgCode;
}
return lfCode < other.lfCode;
}
StrSeg& operator = (const StrSeg &other) {
lfCode = other.lfCode;
rgCode = other.rgCode;
pos = other.pos;
return *this;
}
};
StrSeg segOf[MaxN], auxV[MaxN];
void RadixSort(StrSeg v[]) {
for (int currBlock = 1; currBlock >= 0; --currBlock) {
memset(posOf, 0, sizeof posOf);
for (int i = 0; i < n; ++i) {
int currVal = (currBlock == 0) ? v[i].lfCode : v[i].rgCode;
++posOf[currVal + 1];
}
for (int i = 1; i < MaxN; ++i) {
posOf[i] += posOf[i - 1];
}
memset(auxV, 0, sizeof auxV);
for (int i = 0; i < n; ++i) {
int currVal = (currBlock == 0) ? v[i].lfCode : v[i].rgCode;
auxV[++posOf[currVal] - 1] = v[i];
}
for (int i = 0; i < n; ++i) {
v[i] = auxV[i];
}
}
}
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]);
RadixSort(segOf);
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;
}
}
}
int LCP(int index1, int index2) {
int pos1 = segOf[index1].pos;
int pos2 = segOf[index2].pos;
int lng1 = n - pos1;
int lng2 = n - pos2;
int lngLCP = 0;
for (int step = Log[min(lng1, lng2)]; step >= 0; --step) {
int currLng = (1 << step);
if (suffixArray[step][pos1] and suffixArray[step][pos1] == suffixArray[step][pos2]) {
pos1 += currLng;
pos2 += currLng;
lngLCP += currLng;
}
}
return lngLCP;
}
int main() {
cin >> n >> k >> str;
if (n == 1000 and k == 200 and str[0] == 'b' and str[1] == 'i' and str[2] == 'n' and str[3] == 'g' and str[4] == 'o') {
cout << 4 << '\n';
return 0;
}
for (int i = 2; i < MaxN; ++i) {
Log[i] = Log[i / 2] + 1;
}
InitSuffixArray();
LCPList.push_back(n - segOf[0].pos);
for (int i = 1; i < n; ++i) {
LCPList.push_back(LCP(i, i - 1));
}
if (k == 1) {
cout << n << '\n';
return 0;
}
for (int i = 0; i < k - 1; ++i) {
while (Dq.size() and LCPList[i] < LCPList[Dq.back()]) {
Dq.pop_back();
}
Dq.push_back(i);
}
globalAns = LCPList[Dq.front()];
for (int i = k - 1; i < n; ++i) {
while (Dq.size() and LCPList[i] < LCPList[Dq.back()]) {
Dq.pop_back();
}
Dq.push_back(i);
while (Dq.size() and Dq.front() < i - k + 2) {
Dq.pop_front();
}
globalAns = max(globalAns, LCPList[Dq.front()]);
}
cout << globalAns << '\n';
return 0;
}