题目大意
输入一串仅含有小写字母的字符串, 让某些辅音字母变成大写(一个变大写同种辅音都变大写)。输出使得相邻辅音大小写不同的个数最多的字符串。
思路
枚举所有辅音大小写的变化组合,最多2^19,然后选出最优的状态。本题的重点是怎样保存这个状态,可以用二进制来保存,对于每种状态通过枚举两个辅音字母来统计相邻个数,然后维护一个最优状态。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = (int)1e6 + 10, inf = 0x3f3f3f3f;
char s[maxn];
int n;
int ans, cnt, ansolve;
int cons[30]; // 记录该字符串出现的辅音字母
int mm[30]; // 辅音字母 在一个状态中所处的二进制位置,方便输出答案
int mp[30][30];
int idx(char c) {
return c - 'a';
}
bool judge(char c) {
if(c=='a'||c=='e'||c=='i'||c=='o'||c=='u'||c=='w'||c=='y') {
return false;
}
else return true;
}
void init() {
n = (int)strlen(s);
memset(mp, 0, sizeof(mp));
cnt = 0;
int vis[30];
memset(vis, 0, sizeof(vis));
if(judge(s[0])) {
vis[idx(s[0])] = 1;
cons[cnt++] = idx(s[0]);
mm[idx(s[0])] = 1;
}
for(int i = 1; i < n; i++) {
if(judge(s[i])&&!vis[idx(s[i])]) {
vis[idx(s[i])] = 1;
mm[idx(s[i])] = 1<<cnt;
cons[cnt++] = idx(s[i]);
}
if(judge(s[i-1])&&judge(s[i])) {
mp[idx(s[i-1])][idx(s[i])]++;
}
}
}
void solve() {
int m = 1 << cnt;
for (int zt = 1; zt < m; zt++) {
int sum = 0;
for (int i = 0; i < cnt; i++) {
for (int j = i + 1; j < cnt; j++) {
if (((zt & 1 << i) || (zt & 1 << j)) && !((zt & 1 << i) && (zt & 1 << j))) {
sum += mp[cons[i]][cons[j]];
sum += mp[cons[j]][cons[i]];
}
}
if (ans < sum) {
ans = sum;
ansolve = zt;
}
}
}
//cout << ans << endl;
for (int i = 0; i < n; i++) {
if (judge(s[i]) && mm[idx(s[i])]&ansolve) {
printf("%c", toupper(s[i]));
} else {
printf("%c", s[i]);
}
}
cout << endl;
}
int main() {
//freopen("input.txt", "r", stdin);
freopen("consonant.in", "r", stdin);
freopen("consonant.out", "w", stdout);
while(~scanf("%s", s)) {
init();
solve();
}
return 0;
}