Pagini recente » Cod sursa (job #2326732) | Cod sursa (job #2645231) | Cod sursa (job #2804947) | Cod sursa (job #12400) | Cod sursa (job #2123983)
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct suffix
{
int pos;
pair<int, int> Rank;
bool operator <(const suffix &that) const
{
return Rank < that.Rank;
}
};
class SuffixArray
{
public:
vector<vector<int> > Rank;
vector<int> rankPos;
SuffixArray(const string &s)
{
this->s = s;
int n = s.size();
vector<suffix> v(n);
SetLog();
Rank.resize(log[n] + 3, vector<int>(n));
for(int i = 0; i < n; ++i)
Rank[0][i] = s[i] - 'a', v[i].pos = i;
int k, length;
for(k = 1, length = 1; length / 2 < n; ++k, length *= 2)
{
for(int i = 0; i < n; ++i)
{
v[i].Rank.first = Rank[k-1][v[i].pos];
v[i].Rank.second = v[i].pos+length < n ? Rank[k-1][v[i].pos+length] : -1;
}
sort(v.begin(), v.end());
int current = 0;
Rank[k][v[0].pos] = current;
for(int i = 1; i < n; ++i)
Rank[k][v[i].pos] = v[i].Rank == v[i-1].Rank ? current : ++current;
}
if(length/2 == n)
Rank.pop_back();
}
void PreprocessLcp()
{
int n = s.size();
int x, y, lg = log[n];
vector<int> LCP(n); //LCP intre i si i+1
rankPos.resize(n);
for(int i = 0; i < n; ++i)
rankPos[Rank.back()[i]] = i;
for(int i = 0; i < n-1; ++i)
LCP[i] = GetLogLcp(rankPos[i], rankPos[i+1]);
rmqLcp.resize(lg, vector<int>(n, n));
for(int i = 0; i < n; ++i)
rmqLcp[0][i] = LCP[i];
for(int i = 1; i < lg; ++i)
for(int j = 0; j + (1 << (i - 1)) < n; ++j)
rmqLcp[i][j] = min(rmqLcp[i-1][j], rmqLcp[i-1][j + (1 << (i - 1))]);
}
int GetLogLcp(int x, int y)
{
if(x > y)
swap(x, y);
int n = s.size();
int ret = 0;
int lg = log[n];
for(int step = lg-1; step >= 0 && x < n && y < n; --step)
if(Rank[step][x] == Rank[step][y])
ret |= (1 << step), x += (1 << step), y += (1 << step);
return ret;
}
int GetLcp(int x, int y) // 0-indexed
{
x = Rank.back()[x];
y = Rank.back()[y];
if(x > y)
swap(x, y);
y--;
if(x == y)
return rmqLcp[0][x];
int lg = log[y - x + 1];
if((1 << lg) == y - x + 1)
lg--;
return min(rmqLcp[lg][x], rmqLcp[lg][y - (1 << lg) + 1]);
}
private:
string s;
vector<vector<int> > rmqLcp;
vector<int> log;
void SetLog()
{
log.resize(s.size()+1);
log[1] = 0;
for(int i = 2; i < s.size()+1; ++i)
log[i] = log[i/2] + 1;
}
};
int main()
{
int n, k;
string s;
ifstream in("substr.in");
in >> n >> k >> s;
in.close();
SuffixArray ar(s);
ar.PreprocessLcp();
auto &Rank = ar.Rank.back();
int rasp = 0;
for(int i = 0; i+k < n; ++i)
if(Rank[i] + k - 1 < n)
rasp = max(rasp, ar.GetLcp(i, ar.rankPos[Rank[i] + k - 1]));
ofstream out("substr.out");
out << rasp;
out.close();
return 0;
}