作者 : Xia Xinyu
日期 : 2021-08-14原题链接
题目:
给定一个长度为 n 的由小写字母构成的字符串 s。
请你构造一个长度为 k 的由小写字母构成的字符串 t。
要求,字符串 t 需满足:
字符串 t 在字典序上大于字符串 s。
字符串 t 的字母集是字符串 s 的字母集的子集。一个字符串的字母集是指该字符串包含的所有不同字母的集合,例如 abadaba 的字母集为 {a,b,d}。
字符串 t 在字典序上尽可能小。
保证答案存在。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含两个整数 n 和 k。
第二行包含一个长度为 n 的字符串表示 s。
输出格式
每组数据输出一行满足所有条件的字符串 t。
数据范围
前三个测试点满足 1≤n,k≤3。
所有测试点满足 1≤T≤10,1≤n,k≤105。
同一测试点内,所有 n 的和不超过 105,所有 k 的和不超过 105。
输入样例:
4
3 3
abc
3 2
abc
3 3
ayy
2 3
ba
输出样例:
aca
ac
yaa
baa
思路:分两种情况进行讨论即可
1:若n < k
则原样输出s串,然后再输出s串中最小字符 k - n 次即可
2:若 n >= k
,这时需要从后往前遍历,若当前字符可以找到下一个比自身大的字符就更换(找到后即可跳出循环),否则变成s串中最小字符(因为满足条件——可以找到下一个比自身大的字符后面的字符不影响字典序的大小,所以为满足条件取最小字符即可)
代码:
import java.util.*;
public class Main{
public static char get_min(boolean[] flag){
for(int i = 0;i < flag.length;i++)
{
if(flag[i] == true)
{
return (char)(i + 'a');
}
}
return 0;
}
public static char get_next(boolean[] flag,int index){
int i = index;
for(i = index;i < 26;i++)
{
if(flag[i]) return (char)('a' + i);
}
if(i == 26) return 'f';
return 0;
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int T = in.nextInt();
while(T-- != 0){
int n = in.nextInt();
int k = in.nextInt();
String s = in.next();
var c = s.toCharArray();
var flag = new boolean[26];
for(int i = 0;i < c.length;i++)
{
flag[c[i] - 'a'] = true;
}
if(k > n){
for(char x : c) System.out.print(x);
for(int i = 1;i <= k - n;i++) System.out.print(get_min(flag));
}
else{
boolean f = false;
int index = 0;
for(int i = k - 1;i >= 0;i--){
if(get_next(flag,c[i] - 'a' + 1) != 'f')
{
c[i] = get_next(flag,c[i] - 'a' + 1);
break;
}
else
c[i] = get_min(flag);
}
for(int i = 0;i < k;i++) System.out.print(c[i]);
}
System.out.println();
}
}
}