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;
}