1 条题解
-
0
思路与算法
对每行用栈保存尚未匹配的左括号,定义等级<>为0、()为1、[]为2、{}为3。读左括号时,如果它的等级比当前栈顶更大,就违反内到外的规定;否则压栈。读右括号时必须与栈顶同种,随后弹栈。最终没有违反规则且栈为空才输出YES。
正确性说明
栈顶是最近尚未匹配的左括号,右括号只能与它匹配,保证括号正确配对且不交叉。新内层等级不能大于外层等级,恰好落实题目规定;相同种类可以嵌套,公开样例中的{{}}等对此有证据。相邻独立括号段在栈清空后互不限制。全部扫描完栈为空等价于没有缺失右括号,结合前述条件即为合法。
复杂度
每字符最多入栈一次、出栈一次。设各行长度L_i,总时间O(ΣL_i+组数),每行栈空间O(L_i),最多255。逐行栈和标志初始化O(1),字符缓冲的读取与末尾CR清理包含在总时间内。
易错点
普通括号匹配不足以判定本题,([])虽配对却违反层级;([)]是交叉匹配错误。<>必须位于更高等级内层。空字符串按空匹配处理。每行输出独立结论,不能把上一行未清空的栈带入下一行。
参考代码(C++11)
#include <bits/stdc++.h> using namespace std; int level(char c) { if (c == '<' || c == '>') return 0; if (c == '(' || c == ')') return 1; if (c == '[' || c == ']') return 2; return 3; } int main() { string count; getline(cin, count); string s; while (getline(cin, s)) { if (!s.empty() && s.back() == '\r') s.pop_back(); vector<char> st; bool ok = true; for (char c : s) { int k = level(c); if (c == '<' || c == '(' || c == '[' || c == '{') { if (!st.empty() && k > level(st.back())) ok = false; st.push_back(c); } else if (st.empty() || level(st.back()) != k) ok = false; else st.pop_back(); } cout << (ok && st.empty() ? "YES" : "NO") << '\n'; } }
- 1