这道题做起来好烦啊,说一下思路吧:
像平时括号配对问题一样,能配对的弹出,否则就压入栈(下标),最后得到的栈两两数中间是能配对的(不包括开头结尾),然后依次取数算次数就行了。
代码如下:
#include <cstdio>
#include <map>
#include <stack>
#include <cstring>
#include <algorithm>
using namespace std;
int main()
{
map<char,int> m;
m['('] = 1;
m[')'] = -1;
m['['] = 2;
m[']'] = -2;
char str[100000+22];
int l;
int ans;
while (~scanf ("%s",str))
{
l = strlen(str);
stack<int> s;
ans = 0;
for (int i = 0 ; i < l ; i++)
{
if (m[str[i]] == 1 || m[str[i]] == 2)
s.push(i);
else if (s.empty())
s.push(i);
else if (m[str[i]] + m[str[s.top()]] == 0) //可以配对,弹出
s.pop();
else //不能配对,压入
s.push(i);
}
if (s.empty()) //全部完成匹配
{
for (int i = 0 ; i < l ; i++)
if (m[str[i]] == 2)
ans++;
printf ("%d\n%s\n",ans,str);
}
else
{
int st,endd;
int ans_st,ans_endd; //满足条件的开始于结束位置
int ant;
s.push(l);
while (s.size() != 1)
{
endd = s.top() - 1;
s.pop();
st = s.top() + 1;
ant = 0;
for (int i = st ; i <= endd ; i++)
if (m[str[i]] == 2)
ant++;
if (ant > ans)
{
ans = ant;
ans_st = st;
ans_endd = endd;
}
}
st = 0;
endd = s.top() - 1;
ant = 0;
for (int i = st ; i <= endd ; i++)
if (m[str[i]] == 2)
ant++;
if (ant > ans)
{
ans = ant;
ans_st = st;
ans_endd = endd;
}
if (ans)
{
printf ("%d\n",ans);
for (int i = ans_st ; i <= ans_endd ; i++)
printf ("%c",str[i]);
printf ("\n");
}
else
printf ("0\n\n");
}
}
return 0;
}