实验任务
小光头解开了老鼠的难题,老鼠很高兴,告诉他们,他们需要打败控制这个森林的大魔王才能走出这片森林。如果小光头能再帮他解开一个难题,他就告诉小光头去哪里找这个大魔王。
问题是这样的,老鼠给了一串由由(,),[,],{,},<,>构成的一个括号字符串,找到它的一个最长子串,该子串有正确的括号配对。
数据输入
输入包括多组数据,每组数据只有一行括号字符串,其长度不大于 10000。
数据输出
对于每组数据,输出该括号字符串的最长配对子串。若答案不唯一,则输出最左边一个。
如果答案不存在,则输出“No Solution”。
输入示例
[()()]][]
输出示例
[()()]
解题思路
如果暴力扫描每个子序列,显然会超时。
我们不妨把序列中能匹配的括号标记为1。
[ | ( | ) | ( | ) | ] | ] | [ | ] |
---|---|---|---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
因此只要找到最长且连续的“1”序列,输出对应的括号即可。
参考代码
#include <iostream>
#include <cstring>
#include <map>
#include <stack>
const int maxn = 10010;
using namespace std;
map<char,char> m;
struct P{
char c;
int id;
}ss[maxn];
char str[maxn]; //存 括号字符串
int flag[maxn]; //存 每个括号能否被匹配
int main()
{
m[')'] = '(',m[']'] = '['; //括号映射
m['}'] = '{',m['>'] = '<';
int i;
while(~scanf("%s",str)){
int len = strlen(str);
for (i = 0;i < len;i++){
ss[i].c = str[i];
ss[i].id = i;
} //把字符串复制到结构体中
memset(flag,0,sizeof(flag));
stack<P> s;
P temp = {'#',-1} ;
s.push(temp);
for (i = 0;i < len;i++){
if(m[ss[i].c] == s.top().c){ //如果括号能匹配
flag[i] = 1;
flag [s.top().id] = 1; //这两个位置的flag设为1(true)
s.pop();
}
else
s.push(ss[i]);
}
int cnt=0,s1=0,s2=0,e1=0,e2=0; //cnt记录有多少个连续的1 ,s记录起点,e记录终点
bool first = true;
for (i = 0;i < len;i++){
while (flag[i]){
if (first)
s1 = i,first = false;
cnt++;
if (!flag[i+1])
e1 = i,first = true;
i++;
}
if (e1 - s1 > e2 - s2) //当前序列长度大于已存长度,则更新区间
s2 = s1,e2 = e1;
}
if (!e2)
printf("No Solution");
else{
for (i = s2;i <= e2;i++)
printf("%c",ss[i].c);
}
printf("\n");
}
return 0;
}