51nod 1791合法括号子段

有一个括号序列,现在要计算一下它有多少非空子段是合法括号序列。

合法括号序列的定义是:

1.空序列是合法括号序列。

2.如果S是合法括号序列,那么(S)是合法括号序列。
3.如果A和B都是合法括号序列,那么AB是合法括号序列。

Input
多组测试数据。
第一行有一个整数T(1<=T<=1100000),表示测试数据的数量。
接下来T行,每一行都有一个括号序列,是一个由'('和')'组成的非空串。
所有输入的括号序列的总长度不超过1100000。
Output
输出T行,每一行对应一个测试数据的答案。
Input示例
5
(
()
()()
(()
(())
Output示例
0
1
3
1
2

()是一个合法括号序列,()()是两个合法括号序列。

主要要解决两个合法括号序列组合成新的合法括号序列这个问题。pos[i] 表示第i个右括号与之对应的左括号的位置。ans[i] 表示 在第i个位置一共有多少个。

然后把ans求和就行了。

#include <iostream>
#include <stdio.h>
#include <stack>
#include <string.h>
#define ll long long
using namespace std;
const int N = 1100010;
int t, len;
char str[N];
ll pos[N], ans[N];
int main() {
	scanf("%d",&t);
	while(t--) {
		scanf("%s",str+1);
		len = strlen(str+1);
		for(int i = 0; i <= len; i ++) {
			pos[i] = -1;
			ans[i] = 0;
		}
		stack<int> st;
		for(int i = 1; i <= len; i ++) {
			if(str[i] == '(') st.push(i);
			else {
				if(!st.empty()) {
					pos[i] = st.top();
					st.pop();
				}
			}
		}
		ll toc = 0;
		for(int i = 1; i <= len; i ++) {
			if(pos[i] != -1) {
				ans[i] = ans[pos[i]-1]+1;
				toc += ans[i];
			}
		}
		cout << toc << endl;
	}
	return 0;
}

  

posted @ 2018-04-03 21:42  starry_sky  阅读(255)  评论(0编辑  收藏  举报