您的位置:首页 > 产品设计 > UI/UE

2015 Multi-University Training Contest 6 (hdu 5357 - Easy Sequence)栈的应用

2015-08-11 20:19 381 查看
Easy Sequence

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 643 Accepted Submission(s): 185

Problem Description

soda has a string containing only two characters – ‘(’ and ‘)’. For every character in the string, soda wants to know the number of valid substrings which contain that character.

Note:

An empty string is valid. If S is valid, (S) is valid. If U,V are valid, UV is valid.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

A string s consisting of ‘(’ or ‘)’ (1≤|s|≤1061≤|s|≤10^6).

Output

For each test case, output an integer m=∑i=1|s|(i⋅ansi mod 1000000007), where ansi is the number of valid substrings which contain i-th character.

Sample Input

2

()()

((()))

Sample Output

20

42

Hint

For the second case, ans={1,2,3,3,2,1}, then m=1⋅1+2⋅2+3⋅3+4⋅3+5⋅2+6⋅1=42

其覆盖方案分为两种类型:

例子:”…()(…()()()…)()…” (根据合法序列是否覆盖了“包括了它的最小的括号对”进行分类)

[code]第一部分:倘若它的合法序列覆盖了整个括号对,那么这一部分的方案数等于括号对的总方案数
第二部分:倘若它的合法序列在括号对内,那么这种合法序列一定覆盖了其两边有与其“同级别"(即互不包含)的括号对,设左边有a个,右边有b个,则这一部分的方案数为 (a + 1) * (b + 1)


合并在一起就求出了每个位置的方案数

做法:计算出第 i 个括号的匹配括号位置 match[i],包含它的括号对的左括号位置 pre[i],以及:

[code]对于左括号,其右边的“同级别”的括号个数(包括自己)forward[i] = forward[match[i]+1] + 1
对于右括号,其左边的“同级别”的括号个数(包括自己)backward[i] = backward[match[i]-1] + 1


其中,match[i] 和 pre[i] 可以对序列用栈扫一遍求出,具体做法是:遇到左括号压进栈,遇到右括号就弹栈,之前的栈顶元素与当前元素相互 match,现在的栈顶元素成为当前元素及其 match 的 pre。

最后,ans[i] = ans[match[i]] = ans[pre[i]] + forward[i] * backward[match[i]]

[code]#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=1000100;
const int maxm=1010;
const int MOD=1000000007;
const int INF=0x3f3f3f3f;
char s[maxn];
int N;
int match[maxn],pre[maxn],R[maxn],L[maxn];
LL ans[maxn];
int st[maxn];
void solve(){
    for(int i=1;i<=N;i++){
        s[i]=(s[i]==')');
    }
    memset(match,0,sizeof(int)*(N+2));
    memset(pre,0,sizeof(int)*(N+2));
    memset(L,0,sizeof(int)*(N+2));
    memset(R,0,sizeof(int)*(N+2));
    int top=0;
    for(int i=1;i<=N;i++){
        if(s[i]==0){
            st[++top]=i;
        } else if(top){
            match[st[top]]=i;
            match[i]=st[top];
            --top;
            if(top){
                pre[match[i]]=st[top];
            }
        }
    }
    for(int i=N;i>0;i--){
        if(s[i]==0&&match[i]){
            R[i]=R[match[i]+1]+1;
        }
    }
    for(int i=1;i<=N;i++){
        if(s[i]==1&&match[i]){
            L[i]=L[match[i]-1]+1;
        }
    }
    memset(ans,0,sizeof(LL)*(N+2));
    LL res=0;
    for(int i=1;i<=N;i++){
        if(s[i]==0&&match[i]){
            ans[i]=ans[match[i]]=(ans[pre[i]]+1LL*R[i]*L[match[i]]%MOD)%MOD;
        }
        res+=1LL*i*ans[i]%MOD;
    }
    printf("%I64d\n",res);
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%s",s+1);
        N=strlen(s+1);
        solve();
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: