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;
}
posted @ 2017-08-04 10:41  遗风忘语  阅读(482)  评论(0编辑  收藏  举报