题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5202
题目意思:给出一个长度为 n,只有小写字母和 ? 组成的字符串。现在需要向 ? 的位置填小写字母,使得最终得到的字符串是字典序最小且不是回文串。如果怎么填都不符合结果,则输出 "QwQ"。
首先我大体的解决思路是正确的。
先考虑最简单的情况,有可能整个字符串都不含 “?”。那么如果它不是回文串,就符合题目条件,否则输出"QwQ"
然后考虑有 “?” 的情况。我单纯地把除最后一个 ? 的位置以外的所有 ? 都替换成 a,然后最后一个 ? 暴力试探所有小写字母。如果找不到符合条件的就输出"QwQ"。 这种做法忽略了一种情况。如果字符串是这样 ????aaa,就会无解;但是其实是有解的,即应该输出 aabaaaa 。所以正确的做法还需要考虑倒数第二个?的位置!!!
最后一点就是只有一个 ? 的时候,需要特判一下。
(代码有点长,但非常好理解哦~~~~~)手痒痒,又偷偷玩了下
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 using namespace std; 6 7 int n; 8 const int maxn = 5000 + 5; 9 char s[maxn]; 10 11 bool check(char s[]) 12 { 13 bool flag = true; 14 for (int i = 0; i < n/2; i++) { 15 if (s[i] != s[n-i-1]) { 16 flag = false; 17 break; 18 } 19 } 20 return flag; 21 } 22 23 int main() 24 { 25 #ifndef ONLINE_JUDGE 26 freopen("in.txt", "r", stdin); 27 #endif // ONLINE_JUDGE 28 29 while (scanf("%d", &n) != EOF) { 30 scanf("%s", s); 31 int l = -1; // 初始不能为0,因为可能第一个位置是 ? 32 // 有问号代表可能有解 33 for (int i = 0; i < n; i++) { 34 if (s[i] == '?') { 35 l = i; // 找出最右边第一次出现的问号 36 } 37 } 38 // 没有问号的情况 39 if (l == -1) { 40 printf("%s ", check(s) ? "QwQ" : s); 41 } 42 // 有问号 43 else { 44 // 记下倒数第二个 ? 的位置 45 int pos = -1; 46 // 除了最后的问号,其他问号都填 a 47 for (int i = 0; i < l; i++) { 48 if (s[i] == '?') { 49 pos = i; 50 s[i] = 'a'; 51 } 52 } 53 bool flag = false; 54 for (int i = 0; i <= 25; i++) { 55 // 最后的问号填数,使得不是回文串 56 s[l] = i + 'a'; 57 if (!check(s)) { 58 printf("%s ", s); 59 flag = true; 60 break; 61 } 62 } 63 // 倒数第二个问号的位置不填 a 64 if (!flag) { 65 if (pos == -1) // 排除只有一个问号的情况,? 可能在正中间 66 printf("QwQ "); 67 else { 68 s[l] = 'a'; 69 s[pos] = 'b'; 70 printf("%s ", check(s)? "QwQ" : s); 71 } 72 } 73 } // end else 74 } 75 return 0; 76 }