1 条题解
-
0
思路与算法
对每个输入行,用栈存尚未配对的左括号位置。遇右括号且栈非空就弹栈,否则在该位置标?。全部扫描完后,栈中剩余位置标$,其他位置保留空格。先打印原行,再打印去掉末尾无意义空格的标注行。
正确性说明
按从左到右扫描,栈顶是最近尚未匹配左括号,遇右括号时与它匹配恰好满足最近的嵌套规则。空栈时右括号不存在左配对,必须标?。结束后仍在栈中的左括号没有右配对,必须标$。所有其他字符或已匹配括号均不标注,因此位置和类别准确。
复杂度
每行长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