题目链接:http://codeforces.com/problemset/problem/464/A
题目意思:给出一个长度为 n 且是 tolerable 的字符串s,需要求出字典序最小的长度也为 n 额下一个tolerable 的 字符串,如果求不出则输出“NO”。字符串被认定为tolerable 需要满足:1、字符串的每一位都是取自字母表中前 p 个字母 2、不是回文串。
直接模拟就可以了。主要包括两个步骤:
(1)从后往前遍历,找到目标位置,也就是需要改动的位置下标。
对于当前需要判断的字符(假设数组下标为i),检查 s[i],s[i-1], s[i-2] 的字符是否相同,不等的话代表找出了目标位置。当然,如果 n = 2,只需要判断s[i] 和 s[i-1]
(2)分析这个下标对下的一个位置到结束位置,每个字符需要作怎样的变动。
有可能目标位置变动后,导致下一个字符和它相等,此时设为 a。
处理的时候,将小写字母转化为整数来处理。
以后尽量拿英语来写注释,希望能锻炼一下蹩脚的英语,可能会有点语法问题,大家请见谅。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 const int maxn = 1000 + 10; 8 char s[maxn]; 9 int tmp[maxn]; 10 11 int main() 12 { 13 int n, p; 14 // freopen("in.txt", "r", stdin); 15 while (scanf("%d%d", &n, &p) != EOF) 16 { 17 scanf("%s", s); 18 for (int i = 0; i < n; i++) 19 tmp[i] = s[i] - 'a' + 1; 20 int k; 21 int flag = 0; 22 for (int i = n-1; i >= 0 && !flag; i--) // find the changed object's id 23 { 24 for (int j = tmp[i]+1; j <= p && !flag; j++) 25 { 26 if (i == 0) // n(length) == 1 27 { 28 tmp[k=i] = j; 29 flag = 1; 30 } 31 else if (i == 1 && j != tmp[i-1]) 32 { 33 tmp[k=i] = j; 34 flag = 1; 35 } 36 else if (i >= 2 && j != tmp[i-1] && j != tmp[i-2]) 37 { 38 tmp[k=i] = j; 39 flag = 1; 40 } 41 } 42 } 43 if (!flag) 44 printf("NO "); 45 else 46 { 47 k++; 48 for (; k < n; k++) 49 { 50 flag = 0; 51 for (int j = 1; j <= p && !flag; j++) 52 { 53 if (k == 1 && j != tmp[k-1]) 54 { 55 tmp[k] = j; 56 flag = 1; // ensure every character change only once && the final result is the least lexicographical order 57 } 58 else if (k >= 2 && j != tmp[k-1] && j != tmp[k-2]) 59 { 60 tmp[k] = j; 61 flag = 1; 62 } 63 } 64 } 65 for (int i = 0; i < n; i++) 66 printf("%c", tmp[i]-1+'a'); 67 puts(""); 68 } 69 } 70 return 0; 71 }