1 条题解

  • 0
    @ 2026-10-26 13:21:31

    思路与算法

    对每个输入行,用栈存尚未配对的左括号位置。遇右括号且栈非空就弹栈,否则在该位置标?。全部扫描完后,栈中剩余位置标$,其他位置保留空格。先打印原行,再打印去掉末尾无意义空格的标注行。

    正确性说明

    按从左到右扫描,栈顶是最近尚未匹配左括号,遇右括号时与它匹配恰好满足最近的嵌套规则。空栈时右括号不存在左配对,必须标?。结束后仍在栈中的左括号没有右配对,必须标$。所有其他字符或已匹配括号均不标注,因此位置和类别准确。

    复杂度

    每行长L≤100,时间O(L)、空间O(L),标注串初始化O(L)也计入。多行总时间按各行长度相加,EOF结束;每行重建栈。

    易错点

    标注空格的位置有意义,不能把所有符号挤在一起。只允许去掉行尾空格,不能删除行内空格。原生默认比较器保留行内空格;沙箱也单独按行右裁剪比较,不使用token比较替代位置验收。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        string s;
        while (getline(cin, s)) {
            if (!s.empty() && s.back() == '\r')
                s.pop_back();
            string mark(s.size(), ' ');
            vector<int> st;
            for (int i = 0; i < (int)s.size(); ++i) {
                if (s[i] == '(')
                    st.push_back(i);
                else if (s[i] == ')') {
                    if (st.empty())
                        mark[i] = '?';
                    else
                        st.pop_back();
                }
            }
            for (int x : st)
                mark[x] = '$';
            while (!mark.empty() && mark.back() == ' ')
                mark.pop_back();
            cout << s << '\n' << mark << '\n';
        }
    }
    
    • 1

    信息

    ID
    1757
    时间
    1000ms
    内存
    64MiB
    难度
    进阶
    标签
    递交数
    1
    已通过
    1
    上传者