题目详情
这是英文原题,中文大意在下面~
A. Entertainment in MAC
Congratulations, you have been accepted to the Master's Assistance Center! However, you were extremely bored in class and got tired of doing nothing, so you came up with a game for yourself.
You are given a string 𝑠 and an even integer 𝑛. There are two types of operations that you can apply to it:
- Add the reversed string 𝑠 to the end of the string 𝑠 (for example, if 𝑠=𝑠= cpm, then after applying the operation 𝑠= cpmmpc).
- Reverse the current string 𝑠𝑠 (for example, if 𝑠= cpm, then after applying the operation s= mpc).
It is required to determine the lexicographically smalle string that can be obtained after applying exactly 𝑛 operations. Note that you can apply operations of different types in any order, but you must apply exactly 𝑛𝑛 operations in total.
††A string 𝑎𝑎 is lexicographically smaller than a string 𝑏𝑏 if and only if one of the following holds:
- 𝑎𝑎 is a prefix of 𝑏𝑏, but 𝑎≠𝑏;
- in the first position where 𝑎𝑎 and 𝑏𝑏 differ, the string 𝑎𝑎 has a letter that appears earlier in the alphabet than the corresponding letter in 𝑏.
Input
Each test consists of multiple test cases. The first line contains a single integer 𝑡𝑡 (1≤𝑡≤500 — the number of test cases. The description of the test cases follows.
The first line of each test case contains a single even integer 𝑛 (2≤𝑛≤10^9) — the number of operations applied to the string 𝑠.
The second line of each test case contains a single string 𝑠 (1≤|𝑠|≤100), consisting of lowercase English letters, — the string to which the operations are applied.
Output
For each test case, output a single line — the lexicographically smallest string that can be obtained after applying exactly 𝑛𝑛 operations.
中文大意,除去繁杂的题干
这个问题主要是关于字符串操作的,每个测试用例给定一个字符串和一个偶数次的操作数。你可以选择执行两种操作之一:1.将字符串翻转,2.或者将翻转后的字符串添加到原字符串的末尾。你必须确保总共执行的操作数是给定的偶数。问题的目的是找到经过这些操作后得到的字典序最小的字符串,所谓字典序最小是指在所有通过操作得到的字符串中,按字典排序最小的那个。
字典序排序解释字母顺序或者词典序排序,是一种按照字母顺序(即字母表中的顺序)对字符或者单词进行排序的方式,较早出现在字母表中的字符被认为是较小的。
例子
输入:
4
cpm
根据这个输入,可以应用第二种类型操作(即翻转字符串s)4粗,然后是字符串s将维持cpm这个现状。
解题思路
-
操作限制:根据题目要求,添加翻转后的字符串到原字符串末尾的操作最多只能执行一次。因为这个操作的代价相对较大,可能导致生成的字符串的字典序增大。
-
影响分析:
- 翻转操作:翻转操作改变了字符串的顺序,可能导致生成的字符串的字典序变大或变小。
- 添加反转字符串:将反转后的字符串添加到原字符串的末尾,可能改变了字典序,而且通常而言代价较大。
-
输出形式的考虑:答案要么有原字符串的翻转形式,要么有原字符串的翻转形式。相应的这也是操作1和2在输出上的反应。
-
操作选择:
- 操作次数的控制:由于操作次数是偶数,我们可以在每一对操作中选择一次翻转操作,然后剩下的操作次数用于添加反转字符串,我们只需要执行翻转操作。因为偶数次翻转操作可以将字符串恢复到原始状态,从而得到原字符串或其反转形式。
- 添加反转字符串的位置:我们可以尝试将反转字符串添加到原字符串的末尾,这样做的好处是我们可以保留原字符串的前缀,这些前缀是字典序最小的。
-
算法设计:
- 如果剩余操作次数是偶数,我们可以执行翻转操作,将字符串变为字典序最小的状态。
- 然后,我们通过将反转后的字符串添加到原字符串的末尾来使用剩余的操作次数。
通过这种方式,我们可以确保生成的字符串是字典序最小
代码
#include <stdio.h>
#include <string.h>
// 反转字符串函数
void reverse(char *str) {
int length = strlen(str);
// 交换字符串的前后字符直到中间位置
for (int i = 0; i < length / 2; i++) {
char temp = str[i];
str[i] = str[length - i - 1];
str[length - i - 1] = temp;
}
}
int main() {
int tt;
scanf("%d", &tt); // 输入测试用例的数量
while (tt--) {
int n;
scanf("%d", &n); // 输入操作次数
char s[101];
scanf("%s", s); // 输入字符串
char t[101];
strcpy(t, s); // 将输入的字符串复制给t
reverse(t); // 反转字符串t
// 比较s和t+s,输出字典序最小的结果
if (strcmp(s, t) > 0) {
printf("%s\n", t);
} else {
strcat(t, s); // 将反转后的字符串t连接到s的末尾
printf("%s\n", t);
}
}
return 0;
}
算法分析
时间复杂度分析:
-
翻转操作:翻转字符串的时间复杂度为O(n),其中n是字符串的长度。因为我们最多需要执行n/2次翻转操作,所以总的时间复杂度为O(n^2)。
-
添加反转字符串:添加反转字符串的操作只能执行一次,时间复杂度为O(n)。因为我们需要遍历一次字符串来构造反转后的字符串,并将其添加到原字符串末尾。
因此,整个算法的时间复杂度为O(n^2)。
空间复杂度分析:
对于空间复杂度,我们只需要额外存储一个反转后的字符串t,因此空间复杂度为O(n),其中n是字符串的长度。