题意
有一个括号序列,仅包含英文小写括号,问这个序列中最长的连续完全匹配括号序列有多长,有多少个这么长的连续完全匹配括号序列
思路
对于每一位置我们考虑两个值d[i]表示对于一个右括号它对应的左括号的位置,如果没有就是-1,c[i]表示最早的位置使得从这个位置开始倒现在这个右括号的位置是连续完全匹配括号序列,如果找不到这样的位置就是-1,这样我们根据c[i]就可以算出答案了。我们用一个栈去算d[i]和c[i],首先遇到左括号就入栈,遇到右括号,如果此时栈为空那么d[i]=-1,否则d[i]等于栈顶元素,栈顶出栈,此时c[i]肯定不大于d[i],我们考虑一些d[i]-1这个位置,如果它是右括号且c[d[i]-1]不等于-1的话那么就说明我们c[i]可以到c[d[i]-1]这么远了
代码
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
int d[1000001],c[1000001];
stack<int> st;
char s[1000001];
int main()
{
int l,ans,cnt;
scanf("%s",s);
l=strlen(s);
for(int i=0;i<l;i++)
{
if(s[i]=='(')
st.push(i);
else
{
if(st.empty())
{
d[i]=-1;
c[i]=-1;
}
else
{
d[i]=st.top();
st.pop();
c[i]=d[i];
if(d[i]>=1&&s[d[i]-1]==')'&&c[d[i]-1]!=-1)
c[i]=c[d[i]-1];
}
}
}
ans=0;
cnt=1;
for(int i=0;i<l;i++)
if(s[i]==')'&&c[i]!=-1)
{
if(i-c[i]+1>ans)
{
ans=i-c[i]+1;
cnt=1;
}
else if(i-c[i]+1==ans)
cnt++;
}
printf("%d %d\n",ans,cnt);
return 0;
}