题目
MT2114 - 括号家族
小码哥在研究只有左括号和右括号组成的序列。给出一个括号序列,求出最长合法子串和它的数量(合法的定义:这个序列中左右括号匹配)。
例如:(()不合法,)()(也不合法,但()()和(())合法。
格式
输入格式:
输入一行只有左括号和右括号组成的序列(只包含小括号)。
输出格式:
输出两个数字:最长子字符串的长度,以及此类子字符串的数量,如果没有这样的子字符串,则输出0 1。
样例 1
输入:
()()))()()(()
输出:
4 2
备注
其中:字符串长度小于等于$10^6$。
疑问:
我的代码只通过了三个(测试结果如下图),但是我自己找不出反例。。有没有人能帮忙看看。(最好能给出反例)

思路说明:
总体是用了栈加线性DP
dp数组根据括号种类有两种含义:
对于左括号'(':dp[i]表示该左括号前面邻接的已成功匹配的长度
对于右括号')':dp[i]表示如下:
如果该右括号没有匹配成功,则dp[i]=-1;
否则:
设j为与该右括号匹配的左括号索引,则i+1-j为这对括号的长度,
则dp[i]=i+1-j+dp[j]表示这对括号的长度加上前面邻接的已成功匹配的长度。应该就是以该右括号结尾的成功匹配的最长子串长度。
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
cin>>s;
long long n=s.size();
stack<long long> stk;
vector<long long> dp(n,-1);
long long max=0,cnt=1;
long long len=0;//len用来统计邻接下一个左括号的成功匹配的长度
for(long long i=0;i<n;i++){
if(s[i]=='('){
if(i>0&&s[i-1]=='('){
len=0;//如果前面也是左括号则该左括号前面邻接的成功匹配长度为0
}
stk.push(i);//将左括号索引入栈
dp[i]=len;
}
else{
if(stk.empty()) {//栈空时遇到右括号就跳过同时len=0
len=0;
continue;
}
else{//栈非空该右括号就被匹配到索引为stk.top()的左括号
dp[i]=i-stk.top()+dp[stk.top()]+1;
stk.pop();
len+=2;
}
//下面是统计max和cnt
if(dp[i]>max){
max=dp[i];
cnt=1;
}
else if(dp[i]==max) cnt++;
}
}
cout<<max<<" "<<cnt<<endl;
return 0;
}