Test instructions: Given a string, you divide him into K-strings at most, pick out the largest substring of the dictionary in each substring, and pick out the most dictionary-ordered string from all the selected strings. Now hopefully, the last string to pick out is small enough.
Idea: The last string to pick out is also a substring of the original string. At the same time, the larger the dictionary sequence, the more likely the string is to become the final result. So satisfying monotonicity, we can use the dichotomy method to solve.
First, the suffix array is used to get all the different substrings. Then, the direct two-point answer, determine whether the substring can be constructed to meet the test instructions.
How to construct it.
First, understand that our two-point answer is the largest substring in all substrings. Any substring of the other string cannot be greater than his in the dictionary order.
In this way, we can find out, for the substring starting with I, where to end, can make this substring greater than the two-point answer.
For this answer, in the SA array, all of the preceding substrings are smaller than him, and that end position must be at the end of the entire string.
In the SA array, the string at the back of the answer, if there is no public prefix, you can find a larger one than the answer, regardless of the decomposition. This will not meet the above conditions.
But there's a public prefix. At this time, we are going to construct it from the front to the back. If such a substring is less than k, then we can not allow these substrings to be formed by proper partitioning. If such a substring is greater than k, then no matter how it is split, there will be at least one such substring, in which case the answer is wrong.
Note: The key to this topic is if you construct such a string. Since the suffix array is the embodiment of the suffix, we can recursively construct the string from the go-back.
At the same time, the suffix array is sorted for all the substrings, and the dichotomy method can be used to solve some problems of satisfying monotonicity.
The code is as follows:
#include <cstring> #include <cstdio> #include <algorithm> using namespace std;
const int MAX = 100010;
int k,n;
Char Str[max];
int R[max];
Long Long Sum[max];
int Limit[max];
const int MAXN = 1000100;
int RK[MAXN],SA[MAXN],HEIGHT[MAXN];
int a[maxn],b[maxn],cnt[200000];
The string to be sorted is R, length n, Range r[0]-r[n-1], and the value range is 0-n-1.
Character set is m, range 1-m;
void Radix_sort (int * r, int *a, int *b, int n, int m) {//A radix is sorted by R, stored to B, n in length, and the character set is M-memset (cnt,0,sizeof (CNT));
for (int i = 0; i < n; ++i) ++cnt[r[a[i]];
for (int i = 1; I <= m; ++i) cnt[i] + = cnt[i-1];
for (int i = n-1; I >= 0; i) b[--cnt[r[a[i]]] [= A[i];
} void Calc_sa (int*r, int n, int m) {for (int i = 0; i < n; ++i) rk[i] =i;
Radix_sort (R,RK,SA,N,M);
Rk[sa[0]] = 0;
for (int i = 1; i < n; ++i) rk[sa[i]]= Rk[sa[i-1]] + (r[sa[i]]!=r[sa[i-1]); for (int i = 0; 1<<i< N, ++i) {for (int j = 0; J < N;
++J) {A[j] = rk[j]+1; B[J] = j + (1<<i) >=n?
0:rk[j + (1<<i)] + 1;
SA[J] = j;
} radix_sort (B,sa,rk,n,n);
Radix_sort (A,rk,sa,n,n);
Rk[sa[0]] = 0; for (int j = 1; j < n; ++j) {rk[sa[j]] = Rk[sa[j-1]] + (a[sa[j-1] [! = A[sa[j]] | | b[sa[j-1]]! = B[sa[j]
);
}}}} void Calc_height (int * r,int N) {//Calculate height for (int i = 0; i < n; ++i) rk[sa[i]] = i;
int h = 0;
for (int i = 0; i < n; ++i) {h = h = = 0?0:h-1;
if (rk[i]!= 0) while (r[i + h] = = R[sa[rk[i]-1] + h]) h++;
Height[rk[i]] = h;
}} bool Judge (long long mid) {int pos = lower_bound (sum + 1, sum + 1 + n,mid)-sum-1;
int len = Mid-sum[pos] + Height[pos];
for (int i = 0; i < POS; ++i) limit[sa[i]] = n;
Limit[sa[pos]] = Sa[pos] + len; int mii = height[pos+1];
for (int i = pos + 1; i < n; ++i) {mii = min (mii,height[i]);
Limit[sa[i]] = sa[i] + min (mii,len);
} int need = 1;
Mii = n;
for (int i = 0; i < n; ++i) {if (i = = Limit[i]) return false;
if (i >= mii) {if (++need > K) return false;
Mii = n;
mii = min (mii,limit[i]);
} return true;
} int main (void) {//freopen ("Input.txt", "R", stdin);
while (scanf ("%d", &k), K) {scanf ("%s", str);
n = 0;
for (; str[n];n++) r[n] = Str[n];
Calc_sa (r,n,256);
Calc_height (R,n);
Sum[0] = 0;
for (int i = 1; I <= n; ++i) sum[i] = Sum[i-1] + n-sa[i-1]-height[i-1];
Long long lb = 0,ub = Sum[n];
while (lb + 1 < UB) {Long Long mid = (lb + ub) >> 1;
if (judge (mid)) UB = mid;
else lb = mid; } int pos = Lower_bound (sum+ 1, sum + 1 + n,ub)-sum-1;
int len = Ub-sum[pos] + Height[pos];
pos = Sa[pos];
Str[pos + len] = 0;
printf ("%s\n", str + pos);
} return 0;
}