This is yet another problem dealing with regular bracket sequences.
We should remind you that a bracket sequence is called regular, if by inserting «+» and «1» into it we can get a correct mathematical expression. For example, sequences «(())()», «()» and «(()(()))» are regular, while «)(», «(()» and «(()))(» are not.
You are given a string of «(» and «)» characters. You are to find its longest substring that is a regular bracket sequence. You are to find the number of such substrings as well.
The first line of the input file contains a non-empty string, consisting of «(» and «)» characters. Its length does not exceed 106.
Print the length of the longest substring that is a regular bracket sequence, and the number of such substrings. If there are no such substrings, write the only line containing "0 1".
)((())))(()())
6 2
))(
0 1
题目意思求给出的括号串中最长的合法括号序列
这题目最开始想的用1 -1前缀和解决 但是发现很多情况并不能处理
这里可以这样想 首先)肯定是匹配的最近的没有匹配的(
不然一定出现没有匹配的或者交替匹配的
于是可以把(入栈 遇到)则出栈一个
而 目前两个()之间的括号序列一定是匹配的
于是只需要把所有的(的位置入栈 出栈时计算下即可知道当前括号序列的长度
但是 这里注意到一点 一个合法的括号序列并不一定是(…… 序列 ……)这样的形式
也可能是(……)(……)这样的形式
于是 用一个数组管理到目前位置的合法序列长度 于是每次得到匹配的括号更新这个值即可
有点dp思想
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
using namespace std;
const int M=1e6+5;
char s[M];
int n[M];//保存到当前位置最长的合法序列长度
stack<int> st;
int main()
{
scanf("%s",s+1);
int l=strlen(s+1);
int ml=0,mn=1;
//最大子串长度,子串个数
// int su=0; //前缀和
for(int i=1;i<=l;i++)
{
if(st.empty()&&s[i]==')')
continue;
if(s[i]==')')
{
n[i]=i-st.top()+1+n[st.top()-1];
st.pop();
if(n[i]==ml)
mn++;
if(n[i]>ml)
{
ml=n[i];
mn=1;
}
}
else
st.push(i);
//cout<<"i "<<i<<" nl "<<n[i]<<endl;
}
printf("%d %d\n",ml,mn);
return 0;
}