51Nod 1791 合法括号子段
给定一串括号串,对于其中每个左括号‘(’最多只能找到一个与之相匹配的右括号‘)’。显然,在括号串固定的情况下,括号的匹配是固定不变的。根据题意,空串为合法括号,“()”为合法括号串,若A为合法括号串则”(A)”为合法括号串。那么我们可以先用括号匹配算法(利用栈)可以找出独立括号的配对情况。假设括号匹配对用数组pos[N]表示,初始化为-1,代表没有与之匹配的括号(右括号最终值是-1),pos[i]表示在第pos[i]个位置上的右括号与第i个左括号匹配。即若pos[i]≠−1,第i个位置上肯定是左括号,第pos[i]个位置上肯定是右括号。
找出独立括号后,以每个括号为开头计算以该括号开头,能有多少对合法的括号序列。用ans[i]存储答案,ans[i]表示以第i个括号开始能有多少种合法的序列,状态转移方程:
$$ans[i]=ans[pos[i]+1]+1 i!=-1$$
最后$Ans=\sum_{i=0}^{len-1}ans[i]$
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
const int N = 1100011;
int t;
char s[N];
int pos[N];
ll ans[N];
stack<int>S;
int main()
{
for(scanf("%d",&t);t--;)
{
scanf("%s",s);
int len=strlen(s);
R(i,0,len) pos[i]=-1,ans[i]=0;
while(!S.empty()) S.pop();
R(i,0,len)
{
if(s[i]=='(') { S.push(i);continue; }
if(S.empty()) continue;
pos[S.top()]=i;S.pop();
}
ll Ans=0;
for(int i=len-1;i>=0;--i)
{
if(pos[i]==-1) continue;
ans[i]=ans[pos[i]+1]+1;
Ans+=ans[i];
}
printf("%I64d\n",Ans );
}
return 0;
}
一直地一直地往前走