T2
题目
睿爸喜欢玩串串。
睿爸手里有一个只有小写字母组成的串(S) , 他希望你在里面找出一个字典序最小的子序列(T) , 使得去掉子序列(T)的部分剩下的串是(T)的一个排列。
如果无法找到,请输出("mathrm{Clbtxdy!}") 。
Solution
贪心。
对于每一位我们贪心选取合法、字典序最小的(同时尽可能取位置靠前的)字母。
一个方案合法:当且仅当取掉这个字母之后依旧至少有解。
判断某一字母是否合法,只需统计这个字母用的次数是否超过总数的一半、之后每种字母还有多少个。
(mathrm{Code:})
#include <cstring>
#include <iostream>
const int N = 210;
int n;
char a[N];
int t[27], c[N][27], b[N];
main() {
freopen("string.in", "r", stdin);
freopen("string.out", "w", stdout);
scanf("%s", a + 1);
n = strlen(a + 1);
for (int i = 1; i <= n; ++i) {
int x = a[i] - 'a';
for (int j = 0; j <= 26; ++j) c[i][j] = c[i - 1][j];
++t[x];
++c[i][x];
}
for (int i = 0; i <= 26; ++i) {
if (t[i] & 1) {
puts("Clbtxdy!");
return 0;
}
}
int now = 0;
for (int i = 1; i <= n; ++i) {
int x = a[i] - 'a';
while (c[i][x] * 2 > t[x] + 2 * b[x]) {
for (int j = 0; j <= 26; ++j) {
if (c[i][j] - c[now][j] && b[j] * 2 < t[j]) {
++b[j];
putchar(j + 'a');
for (int k = now + 1; k <= i; ++k)
if (a[k] == j + 'a') {
now = k;
break;
}
break;
}
}
}
}
return 0;
}