第一次用md格式,可能打出来比较丑:)
先说一下题意:给你长度为N的字符串S。可以取当前字符串首位/最末位的字符放在新的字符串,求进行N次操作后字典序最小的新字符串
解释一下样例:
Input:
6
ACDBCB
首位是A,末位是B,显然字典序:A < B,所以目前的新字符串就是
A
现在首位是C,末位是B,显然字典序:B < C,所以目前的新字符串就是
AB
以此类推,答案就是
Output:
ABCBCD
这个题贪心意图也挺明显的。一开始拿到这道题还想的是暴力的取最前/最后的字符然分别放入新串中用strcmp做,但1s时间肯定不够用。书上的方法就很巧妙了:)。
因为题意的特点可以看出,对于S的反转串S’求出的答案和用S求出的答案是一样的,所以就可以先构造串S的反转S’,再通过strcmp决定是用S的首位或是S’的首位(即S的末位)。以此类推直到S被删空。
题目中
N<=2000
,所附的代码平均情况在规定时间内完全可以实现,代码如下↓
#include <stdio.h>
#include <string.h>
#define MaxN 2100
int n, cnt, len;
char str1[MaxN], str2[MaxN], ans[MaxN];
int main() {
scanf("%d\n", &n);
for (int i = 1; i <= n; i++) {
str1[i] = getchar();
getchar();
str2[n - i + 1] = str1[i];
}
str1[0] = str2[0] = '0';
for (int T = 1; T <= n; T++) {
if (strcmp(str1, str2) >= 0) {
ans[++cnt] = str2[1];
len = strlen(str2);
for (int i = 1; i <= len; i++)
str2[i] = str2[i + 1];
str2[strlen(str2)] = '\0';
str1[strlen(str1) - 1] = '\0';
}
else if (strcmp(str1, str2) < 0) {
ans[++cnt] = str1[1];
len = strlen(str1);
for (int i = 1; i <= len; i++)
str1[i] = str1[i + 1];
str2[strlen(str2) - 1] = '\0';
str1[strlen(str1)] = '\0';
}
}
for (int i = 1; i <= n; i++) {
printf("%c", ans[i]);
if (i % 80 == 0)
printf("\n");
}
return 0;
}