题意:给定长度为n的字符串s,将s任意拆分成k个部分,求k个部分中字典序最大的最小字典序
思路:
因为是任意拆分,所以将s中的字母从小到大排序,那么字典序最小的字母为s[1],记它的个数为p
实际上要求的还是最小字典序,那么在构造这k个部分的过程中,应始终选用可选的最小字母
有三种情况:
1.(p<k),则(k)个部分中必有(p)个以s[1]开头,而第(p+1)个则以更大的字母开头,故第(k)个部分应以s[k]这个字母为开头,那么它一定是字典序最大的那个。由于要求最小字典序,则不应在其后继续接字母,剩余字母都将安排到(p)个部分中。所以答案应该为s[k]
2.(k≤p<n),则(k)个部分都以s[1]为开头,答案应在后直接接剩下所有的串,就直接能保证满足题意
3.(p=n),则k个部分平均分配所有字母才能保证答案是最小的字典序,答案应该是(n/k)个s[1]
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 3e5 + 10;
typedef long long LL;
LL gcd(LL a, LL b) {return b ? gcd(b, a % b) : a;}
LL lcm(LL a, LL b) {return a * b / gcd(a, b);}
char s1[100000 + 10];
int main()
{
int t; cin >> t; while (t--){
int n, k;
cin >> n >> k;
cin >> s1+1;
sort(s1+1, s1 + n+1);//找出字典序前k小的字母
if (s1[1] != s1[k]) cout << s1[k] << endl;
//如果与s1[1]相同的字母小于k个,那么符合要求的答案必为s1[k]这个字母
else if (s1[n] != s1[k + 1]) cout << s1[1] << s1 + k + 1 << endl;
//如果与s1[1]相同的字母大于等于k个,但不是全部都相同
//那么答案以s1[1]开头,后面接从k+1个字母开始的串
else {
//全部相同,平均分配
cout << s1[1];
for (int i = 1; i <= (n - 1)/ k; i++) cout << s1[k + 1];
cout << endl;
}
}
return 0;
}