Pagini recente » Cod sursa (job #1984852) | Cod sursa (job #580438) | Cod sursa (job #2311228) | Cod sursa (job #832617) | Cod sursa (job #2602505)
//#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
using namespace std;
ifstream cin("substr.in");
ofstream cout("substr.out");
const int NMAX = 16384;
int N, K;
char s[NMAX + 2];
struct sufix
{
int startingPos;
pair <int, int> rnk;
};
sufix v[NMAX + 2], aux[NMAX + 2];
int count[NMAX + 2], newRank[NMAX + 2], posv[NMAX + 2];
bool firstTime;
void BucketSort()
{
///sortare dupa rnk.second
for(int i = 0; i <= N; i++)
count[i] = 0;
for(int i = 1; i <= N; i++)
count[v[i].rnk.second]++;
if(!firstTime)
{
firstTime = true;
for(int i = 1; i < 256; i++)
count[i] += count[i - 1];
}
else
{
for(int i = 1; i <= N; i++)
count[i] += count[i - 1];
}
for(int i = N; i >= 1; i--)
aux[count[v[i].rnk.second]--] = v[i];
for(int i = 1; i <= N; i++)
v[i] = aux[i];
///sortare dupa rnk.first si rnk.second
for(int i = 0; i <= N; i++)
count[i] = 0;
for(int i = 1; i <= N; i++)
count[v[i].rnk.first]++;
for(int i = 1; i <= N; i++)
count[i] += count[i - 1];
for(int i = N; i >= 1; i--)
aux[count[v[i].rnk.first]--] = v[i];
for(int i = 1; i <= N; i++)
v[i] = aux[i];
///reetichetare
int k = 0;
newRank[1] = ++k;
for(int i = 2; i <= N; i++)
if((v[i].rnk.first > v[i - 1].rnk.first) || (v[i].rnk.first == v[i - 1].rnk.first && v[i].rnk.second > v[i - 1].rnk.second))
newRank[i] = ++k;
else
newRank[i] = k;
for(int i = 1; i <= N; i++)
v[i].rnk.first = newRank[i];
for(int i = 1; i <= N; i++)
posv[v[i].startingPos] = i;
}
void BuildSuffixArray()
{
for(int i = 1; i <= N; i++)
{
v[i].startingPos = i;
v[i].rnk.first = 0;
v[i].rnk.second = s[i] - '0';
}
BucketSort();
for(int l = 2; l < 2 * N; l *= 2)
{
for(int i = 1; i <= N; i++)
if(v[i].startingPos + l / 2 <= N)
v[i].rnk.second = v[posv[v[i].startingPos + l / 2]].rnk.first;
else
v[i].rnk.second = 0;
BucketSort();
}
}
int lcp[NMAX + 2];
void ComputeLCP()
{
int current = 0;
for(int i = 1; i <= N; i++)
{
int x = posv[i], posX = i, posY = v[x + 1].startingPos;
while(posX + current <= N && posY + current <= N && s[posX + current] == s[posY + current])
current++;
lcp[x] = current;
current = max(0, current - 1);
}
}
const int LOGMAX = 14;
vector <int> rmq[LOGMAX + 1];
int lg2[NMAX + 2];
void BuildRmq()
{
for(int i = 2; i <= N; i++)
lg2[i] = lg2[i / 2] + 1;
for(int i = 1; i <= N; i++)
rmq[0].push_back(lcp[i]);
for(int i = 1; i <= LOGMAX; i++)
if((1 << i) > rmq[0].size()) break;
else
{
for(int j = 0; j < rmq[0].size(); j++)
if((1 << i) + j > rmq[0].size()) break;
else rmq[i].push_back(min(rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]));
}
}
int QueryRmq(int l, int r)
{
l--, r--;
int k = lg2[r - l + 1];
return min(rmq[k][l], rmq[k][r - (1 << k) + 1]);
}
bool isOk(int l)
{
for(int i = 1; i <= N - K + 1; i++)
if(QueryRmq(i, i + K - 1) >= l)
return true;
return false;
}
int main()
{
cin >> N >> K;
cin >> (s + 1);
if(K == 1)
{
cout << N << '\n';
return 0;
}
BuildSuffixArray();
ComputeLCP();
BuildRmq();
/*
for(int i = 1; i <= N; i++)
{
cout << lcp[i] << ' ';
for(int j = v[i].startingPos; j <= N; j++)
cout << s[j];
cout << '\n';
}
*/
K--;
int st = 1, dr = N, sol = 0;
while(st <= dr)
{
int mid = (st + dr) >> 1;
if(isOk(mid))
{
sol = mid;
st = mid + 1;
}
else
dr = mid - 1;
}
cout << sol << '\n';
return 0;
}