一个log的题被我强行写成了两个log
诶再怎么样过了就是了
构建SA,然后二分答案,贪心判断至少要剪断多少次才能使得答案成为最大的
/**************************************************************
Problem: 4310
User: di4CoveRy
Language: C++
Result: Accepted
Time:12576 ms
Memory:10084 kb
****************************************************************/
#include
#define N 200050
#define INF (1<<30)
#define xx first
#define yy second
#define MP(x,y) make_pair(x,y)
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
int sa[N],rank[N],nsa[N],nrank[N],height[N],n,k;
LL sum[N];
char s[N];
void _sort(int j) {
memset(sum,0,sizeof(sum));
for (int i=1;i<=n;i++) sum[ rank[i+j] ]++;
for (int i=1;i<=n;i++) sum[i] += sum[i-1];
for (int i=n;i>=1;i--) nsa[ sum[rank[i+j]]-- ] = i;
memset(sum,0,sizeof(sum));
for (int i=1;i<=n;i++) sum[ rank[i] ]++;
for (int i=1;i<=n;i++) sum[i] += sum[i-1];
for (int i=n;i>=1;i--) sa[ sum[rank[ nsa[i] ]]-- ] = nsa[i];
}
void _sa() {
memset(sum,0,sizeof(sum));
for (int i=1;i<=n;i++) rank[i] = s[i];
for (int i=1;i<=n;i++) sum[ rank[i] ]++;
for (int i=1;i<=255;i++) sum[i] += sum[i-1];
for (int i=n;i>=1;i--)
sa[ sum[rank[i]]-- ] = i;
nrank[ sa[1] ] = 1;
for (int i=2,p=1;i<=n;i++)
nrank[ sa[i] ] = rank[ sa[i] ] == rank[ sa[i-1] ] ? p : ++p;
for (int i=1;i<=n;i++) rank[i] = nrank[i];
for (int j=1;j<=n;j<<=1) {
_sort(j);
nrank[ sa[1] ] = 1;
for (int i=2,p=1;i<=n;i++) {
if (rank[ sa[i] ] != rank[ sa[i-1] ] || rank[ sa[i]+j ] != rank[ sa[i-1]+j ]) p++;
nrank[ sa[i] ] = p;
}
for (int i=1;i<=n;i++) rank[i] = nrank[i];
}
return ;
}
void _hi() {
for (int i=1,j=0;i<=n;i++) {
if (rank[i]==1) continue;
for (;s[i+j]==s[sa[rank[i]-1]+j];j++);
height[rank[i]]=j;
if (j) j--;
}
return ;
}
int tr[4*N],ll,rr;
#define tmd ( (l + r) >> 1 )
#define ls l,tmd,t<<1
#define rs tmd+1,r,t<<1^1
int build(int l,int r,int t) {
return l == r ? tr[t] = height[l] : tr[t] = min( build(ls) , build(rs) );
}
int query(int l,int r,int t) {
if (l > rr || r < ll) return INF;
if (l >= ll && r <= rr) return tr[t];
int p1 = query(ls);
int p2 = query(rs);
return min(p1,p2);
}
pii get(LL x) {
for (int i=1;i<=n;i++)
if (sum[ sa[i] ] >= x) {
x = x - sum[ sa[i-1] ] + height[i];
return MP(sa[i],x);
}
assert(0); return MP(0,0);
}
int lcp(int p1,int p2) {
p1 = rank[p1] , p2 = rank[p2];
if (p1 > p2) swap(p1,p2);
ll = p1 + 1 , rr = p2;
return query(1,n,1);
}
int go(pii A) {
int ret = 1 , last = n;
for (int i=n;i>=1;i--) {
if (s[i] > s[A.xx]) return INF;
int tmp = lcp(A.xx,i);
if (A.xx == i && last-i+1 <= A.yy) continue;
if (tmp > A.yy) {
last = i , ret++;
continue;
}
if (tmp >= last-i+1) continue;
if (s[i+tmp] <= s[A.xx+tmp]) continue;
last = i , ret++;
}
return ret;
}
void _solve() {
memset(sum,0,sizeof(sum));
for (int i=1;i<=n;i++) {
int len = n-sa[i]+1;
sum[ sa[i] ] = sum[ sa[i-1] ] + len - height[i];
}
build(1,n,1);
LL l = 1 , r = sum[ sa[n] ];
while (l < r) {
LL mid = (l + r) >> 1;
pii cur = get(mid);
if (go(cur) > k) l = mid+1; else r = mid;
}
pii ans = get(l);
for (int i=ans.xx;i<=ans.xx+ans.yy-1;i++) printf("%c",s[i]); puts("");
}
int main() {
// freopen("flea.in","r",stdin);
// freopen("flea.out","w",stdout);
scanf("%d",&k);
scanf("%s",s+1); n = strlen(s+1);
_sa(); _hi();
_solve();
return 0;
}