top1编程
← 返回题目
题解

复原字符串

1 条题解

  • 0
    @ 2026-8-5 10:15:42

    解题思路

    回文串从左往右读、从右往左读都一样,所以它有一个重要特点:第 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