In this problem, the task is to distribute the given n \cdot l letters into words of length , sorted lexicographically, so that the -th word is as lexicographically small as possible.
The lexicographical order of words is determined character by character from left to right. Therefore, to minimize the -th word, one must place the smallest possible letters in its earliest positions (starting from the left), without violating the lexicographical order of all words.
This leads to the following greedy algorithm:
Sort all the letters of the input string in ascending order.
Construct a two-dimensional array of characters
where each row represents a separate word.
Fill the array column by column from left to right, since the columns correspond to positions in the words and determine their lexicographical order.
Filling the first column
In the first column, assign letters only to the rows with numbers from to , using the smallest available letters.
Place these letters from top to bottom to maintain the lexicographical order.
The rows numbered k + 1, ..., n are not filled at this stage, as they do not affect the minimality of the -th word.
This way, we ensure that the first character of the -th word is minimal.
Filling the remaining columns
For each column j = 2, 3, ..., l:
Among the rows 1, ..., k, find the smallest index such that the rows and match in all previous columns 1, ..., j - 1.
The set of rows consists of all words that are indistinguishable from the -th word on the current prefix and therefore must remain no greater than it.
In column , assign the smallest available letters only to the rows from to , from top to bottom.
4. Repeat this process until all characters of the -th word are fixed.
Filling the remaining cells
After the -th word has been fully constructed:
All remaining letters can be distributed arbitrarily, as long as the lexicographical order is not violated.
• For example, the remaining letters can be filled into the array sequentially, row by row from top to bottom and left to right, in sorted order.
Correctness
In each column, we minimize the current character of the -th word.
We assign identical or non-decreasing letters to all words that match the -th word on the current prefix, so the order of the words is preserved.
Once the -th word is fully constructed, no further actions can make it larger.
Therefore, the resulting -th word is lexicographically minimal.
Example
Let's consider the following test:
6 3 6
fgahhfgaaebdcbbebcHere, we need to construct words of length , using all the letters, so that the th word in the lexicographically sorted list is minimal.
Sort the letters of the input string:
There are 18 = 6 \cdot 3 letters in total, which corresponds to a 6 × 3 table.
Column 1. Fill the first column with letters from top to bottom, from the first to the sixth row, since the sixth row is the one we are interested in.
Column 2. Now consider the rows whose prefix matches the prefix of the th row. The prefix of the th row after the first column is "". The matching rows are , and . The smallest index among them is pt = 4.
In the second column, assign the smallest available letters to the rows numbered from to .
Column 3. Again, we look for the rows whose prefix matches "" (after filling the first two columns). The matching rows are and . The smallest index among them is pt = 5. Assign the smallest available letters to the rows numbered from to . Now the th word is fully constructed and equals "".
Filling the remaining letters
After the th word has been fixed, the remaining letters can be distributed in any valid way. For example, we can fill the table row by row from top to bottom and left to right with the remaining letters in lexicographical order.
Let's consider the first test case:
3 2 2
abcdefSort the letters of the input string:
We need to fill a matrix of words, each of length , lexicographically minimizing the nd word.
First, fill the first column with letters from top to bottom, only for the rows from to , since these are the ones that affect the minimality of the nd word.
Next, move to the second column. It should be filled starting from the earliest row whose prefix matches the prefix of the nd row. In this case, that row is the nd row itself, so pt = 2. Fill the second column with letters from row to row .
After that, distribute the remaining letters in lexicographical order, row by row from top to bottom and left to right, which completes the construction of a valid answer.
Algorithm implementation
Read the input data.
cin >> n >> l >> k;
cin >> s;Sort the letters of the input string. Let the current letter being processed be .
pos = 0;
sort(s.begin(), s.end());Declare the result matrix , consisting of rows and columns, where each row corresponds to a word of length .
vector<string> v(n, string(l, ' '));We'll distribute the letters in column , filling the rows from to k - 1 inclusive (row numbering starts from zero).
int pt = 0;
for (j = 0; j < l; j++)
{
for (i = pt; i < k; i++)
v[i][j] = s[pos++];Move the pointer forward (pt++) until the -th character of the (k - 1)-th row matches the -th character of row . As a result, points to the row with the smallest index that currently matches the prefix of the (k - 1)-th row.
while (v[pt][j] != v[k - 1][j]) pt++;
}After that, fill the remaining cells of the matrix. To do this, go through the rows from top to bottom and the columns from left to right, distributing the remaining letters.
for (i = 0; i < n; i++)
for (j = 0; j < l; j++)
if (v[i][j] == ' ') v[i][j] = s[pos++];Print the answer.
for (i = 0; i < n; i++)
cout << v[i] << endl;