题解
复原字符串
1 条题解
-
0
解题思路
回文串从左往右读、从右往左读都一样,所以它有一个重要特点:第 i 个字符一定等于第 n-1-i 个字符。我们可以把字符串“对折”,一对一对地检查。
0(数字零)表示看不清的字母,它可能是大写字母 A~Z 里的任意一个。我们把左右两边一对一对来看,分三种情况:情况 1:两个字母都看得清 如果它们不相等,那这串永远不可能回文,直接输出
IMPOSSIBLE。情况 2:一个看得清,一个看不清 看不清的那个只能填成和看得清的那边一样的字母,这样才能回文。比如 A 对 0,0 只能填 A。这种填法只有一种,所以可以放心填。
情况 3:两个都看不清 这个位置可以填 A~Z 任意一个字母,有 26 种选择,答案不唯一,输出
IMPOSSIBLE。另外,如果字符串长度是奇数,正中间那个字符单独成一对:它如果是
0,也有 26 种选择,不唯一,输出IMPOSSIBLE。用题目例子验证:
ABA00:A 对 0,填 A;B 对 0,填 B;中间的 A 看得清。唯一复原成ABABA,正确输出。AB0BA:两边 A-A、B-B 都一致,但中间是0,有 26 种选择,输出IMPOSSIBLE。ABC0CDD:最左边 A 和最右边 D 不相等,不可能是回文,输出IMPOSSIBLE。
参考代码
// P4554 复原字符串:判断能否唯一复原成回文串 #include <iostream> #include <string> using namespace std; int main() { int n; string s; cin >> n >> s; // 读入长度和字符串(0表示看不清) bool ok = true; // ok=true表示可以唯一复原 // 一对一对检查,回文串要求第i位和第n-1-i位相同 for (int i = 0; i < n / 2; i++) { char a = s[i], b = s[n - 1 - i]; // 两个字母都看得清却不相等:不可能回文 if (a != '0' && b != '0' && a != b) { ok = false; break; } // 两个都看不清:这个位置可以填26个字母中的任意一个,不唯一 if (a == '0' && b == '0') { ok = false; break; } // 一个看不清:只能填成和对面一样的字母,这样才唯一 if (a == '0') s[i] = b; if (b == '0') s[n - 1 - i] = a; } // 奇数长度时中间那个字符看不清,同样有26种选择,不唯一 if (n % 2 == 1 && s[n / 2] == '0') ok = false; if (!ok) cout << "IMPOSSIBLE" << endl; else cout << s << endl; // 唯一复原成功,输出回文串 return 0; }复杂度分析
- 只需要把字符串左右配对扫一遍,每个位置处理一次。
- 总时间复杂度 O(n),空间复杂度 O(1)(直接在原字符串上修改)。
- 1