# 跳蚤 BZOJ 4310

【问题描述】

【输入格式】

【输出格式】

【样例输入】

13
bcbcbacbbbbbabbacbcbacbbababaabbbaabacacbbbccaccbcaabcacbacbcabaacbccbbcbcbacccbcccbbcaacabacaaaaaba

【样例输出】

cbc

【数据范围】

S的长度<=100000

ababa

a           a                                 5 + 1 - 0 - 5 = 1

aba       a ab aba                      5 + 1 - 2 - 3 = 1

ababa   a ab aba abab ababa    5 + 1 - 3 - 1 = 2

ba         b ba                            5 + 1 - 0 - 4 = 2

baba     b ba bab baba             5 + 1 - 2 - 2 = 2

#include<algorithm>#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
using namespace std;
const int me = 1000233;
int k;
int n;
int ansl;
int ansr;

int w[me];
int x[me];
int sa[me];
int he[me];
int rank[me];

int lg[me];
int f[23][me];

char s[me];
inline void Sa()
{
int m = 26;
for(int i = 1; i <= n; ++i) ++w[x[i] = s[i] - 'a' + 1];
for(int i = 1; i <= m; ++i) w[i] += w[i - 1];
for(int i = n; i >= 1; --i) sa[w[x[i]]--] = i;
for(int k = 1; k <= n; k <<= 1)
{
int t = 0;
for(int i = n; i >= n - k + 1; --i) rank[++t] = i;
for(int i = 1; i <= n; ++i)
if(sa[i] > k)
rank[++t] = sa[i] - k;
for(int i = 1; i <= m; ++i) w[i] = 0;
for(int i = 1; i <= n; ++i) ++w[x[i]];
for(int i = 1; i <= m; ++i) w[i] += w[i - 1];
for(int i = n; i >= 1; --i) sa[w[x[rank[i]]]--] = rank[i];
m = 0;
for(int i = 1; i <= n; ++i)
{
int u = sa[i], v = sa[i - 1];
if (x[u] != x[v] || x[u + k] != x[v + k]) rank[u] = ++m;
else rank[u] = m;
}
if (n == m) break;
for(int i = 1; i <= n; ++i) swap(x[i], rank[i]);
}
int tot = 0;
for(int i = 1; i <= n; ++i)
{
if(tot) --tot;
int e = sa[rank[i] - 1];
while (s[e + tot] == s[i + tot]) ++tot;
he[rank[i]] = tot;
}
}
inline void Log()
{
lg[1] = 0;
for(int i = 2; i <= n; ++i)
lg[i] = (i == (i & (-i))) ? lg[i - 1] + 1 : lg[i - 1];
}
inline void Rmq()
{
for(int i = 1; i <= n; ++i) f[0][i] = he[i];
for(int i = 1; i <= lg[n]; ++i)
for(int j = 1; j <= n; ++j)
f[i][j] = min(f[i - 1][j], f[i - 1][j + (1 << (i - 1))]);
}
inline void Get(const long long &mi, int &u, int &v)
{
long long e, pre;
e = 0;
for(int i = 1; i <= n; i ++)
{
pre = e;
e += n + 1 - he[i] - sa[i];
if (e >= mi)
{
u = sa[i];
v = sa[i] + mi - pre + he[i] - 1;
return;
}
}
}
inline int Lcp(const int &x, const int &y)
{
if (x == y) return n - x;
int a = rank[x], b = rank[y];
if (a > b) swap(a, b);
int e = lg[b - a];
return min(f[e][a + 1], f[e][b - (1 << e) + 1]);
}
inline bool Com(const int &l1, const int &r1, const int &l2, const int &r2)
{
int len1 = r1 - l1 + 1, len2 = r2 - l2 + 1, lcp = Lcp(l1, l2);
if (len1 <= len2 && lcp >= len1) return true;
if (len1 > len2 && lcp >= len2) return false;
if (lcp >= len1 && lcp >= len2) return len1 <= len2;
return s[l1 + lcp] <= s[l2 + lcp];
}
inline bool Check(const long long &mi, int &u, int &v)
{
Get(mi, u, v);
int num = 0, last = n;
for(int i = n; i >= 1; --i)
{
if (s[u] < s[i]) return false;
if (!Com(i, last, u, v)) ++num, last = i;
if (num >= k) return false;
}
return true;
}
inline void Two()
{
long  long l, r, mi;
int u, v;
l = 1;
r = 0;
for(int i = 1; i <= n; ++i) r += n + 1 - sa[i] - he[i];
while(l <= r)
{
mi = (l + r) >> 1;
if(Check(mi, u, v))
{
ansl = u;
ansr = v;
r = mi - 1;
}
else l = mi + 1;
}
}
int main()
{
scanf("%d%s", &k, s+1);
n = strlen(s+1);
Sa();
Log();
Rmq();
Two();
for(int i = ansl; i <= ansr; ++i) printf("%c", s[i]);
}
posted @ 2017-01-26 11:51  草根柴鸡  阅读(181)  评论(0编辑  收藏  举报