目录
150. 括号画家
题目描述:
输入格式:
输入一行字符串。
输出格式:
输出一行整数,表示完美括号的最大长度
思路解析
首先这是经典题目 -- “括号匹配” 的变形。所以,我们能够很快反应到需要使用 “栈” 结构来处理该问题。从更加一般的角度来说,这道题属于 “栈” 结构处理的完全匹配关系。
所以,我们可以很快设计出以下代码段:
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int MAX_LEN = 1e5 + 10;
char str[MAX_LEN];
int main() {
vector<char> stk;
char ch;
int res = 0;
int tmp_res = 0; // 记录临时答案
scanf("%s", str);
int len = strlen(str);
for (int i = 0; i < len; ++i) {
if (str[i] == '(' || str[i] == '[' || str[i] == '{') stk.push_back(str[i]);
else {
if (stk.size() && (str[i] - stk.back() == 2 || str[i] - stk.back() == 1)) stk.pop_back(), tmp_res += 2;
else {
stk.push_back('#'); // 压入阻隔信息
res = max(res, tmp_res);
tmp_res = 0;
}
}
}
res = max(res, tmp_res);
printf("%d", res);
return 0;
}
但是,这样的代码段存在BUG。 例如,我们面对测试数据 "((([]{}((()" 时,上述代码会返回 6。而正确答案应该是 4。
这样的BUG来自于上述代码段的“缓式评估”,注意 “栈” 在处理问题时,几乎都运用到了缓式评估的思想。此时,这种思想就成了BUG的来源,因为它会连接本该断开的括号序列。
面对这道难题,我们应该知道当匹配发生时,如果栈不为空,我们不应该直接让 tmp_res += 2。而是单独计算此时的括号序列长度。所以我们需要知道下标信息。但是,下标信息又可以告诉我们字符信息。所以,我们空间就可以减少。
#include <iostream>
#include <stack>
#include <cstring>
using namespace std;
stack<int>stk;
int i,ans;
char str[114514],c,cc;
int main()
{
cin>>str;
int size = strlen(str);
for(i = 0;i < size; ++i)
{
c=str[i];
if(stk.size())
{
cc=str[stk.top()];
if((c==')'&&cc=='(')||(c==']'&&cc=='[')||(c=='}'&&cc=='{')) stk.pop();
else stk.push(i); // 压入阻隔信息/压入信息
} // 尝试匹配
else stk.push(i); // 压入阻隔信息/压入信息
if(stk.size()) ans=max(ans,i-stk.top()); // 栈有剩余,单独计算长度
else ans=i+1; // 没有剩余长度就是 i - (-1) == i + 1
}
cout<<ans;
return 0;
}