给一个括号序列,求满足括号匹配的最长子串长度和个数。
可以用栈来依次记录序列中的左括号位置,每当出现一个右括号,判断栈是否为空,若不为空,用此时右括号的位置i减去最近的左括号位置再+1即可得到串的长度。
需要注意的是这种情况:()(),在第二个括号之前已经有符合条件的串,这里需要记录左括号之前的位置已经得到的串的长度。设dp[i]表示到第i个右括号所获串的长度。
则dp[i]=dp[t-1]+i-t+1。t表示离i最近的那个左括号的位置。
#include<bits/stdc++.h>
using namespace std;
char s[1000005];
int dp[1000005];
stack<int> st;
int main()
{
scanf("%s",s+1);
int cnt=0,ans=0,i,l=strlen(s+1);
for(i=1;i<=l;++i)
{
if(s[i]=='(') st.push(i);
else
{
if(!st.empty())
{
int t=st.top();
st.pop();
dp[i]=dp[t-1]+i-t+1;
if(dp[i]>ans)
{
ans=dp[i];
cnt=1;
}
else if(dp[i]==ans) ++cnt;
}
}
}
if(!ans) cnt=1;
printf("%d %d\n",ans,cnt);
return 0;
}
看到这题还有另一种方法,空间复杂度要低一些。
就是:从前往后寻找匹配左括号的最长子串长度,再从后往前求匹配右括号的最长子串长度。取二者的最大值。