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; }