有一个括号序列,现在要计算一下它有多少非空子段是合法括号序列。
合法括号序列的定义是:
1.空序列是合法括号序列。
2.如果S是合法括号序列,那么(S)是合法括号序列。
3.如果A和B都是合法括号序列,那么AB是合法括号序列。
第一行有一个整数T(1<=T<=1100000),表示测试数据的数量。
接下来T行,每一行都有一个括号序列,是一个由'('和')'组成的非空串。
所有输入的括号序列的总长度不超过1100000。
5 ( () ()() (() (())
0 1 3 1
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <cstring> typedef long long ll; using namespace std; /* 竟然会超时,memset都会超时,简直了 */ char str[1100010]; ll dp[1100010]; int pos[1100010]; int main() { int T; scanf("%d",&T); while(T--) { scanf("%s",str); stack<int> stk; int len=strlen(str); for(int i=0;str[i];i++)//对括号进行一对一的匹配操作 { dp[i]=0; pos[i]=-1; if(str[i]=='(') { stk.push(i); continue; } if(stk.empty()) continue; int p=stk.top(); pos[p]=i;//对()进行标记,p '(' , pos[p] ')',这样的话,我们就可以在后面计数的时候直接相加了。 stk.pop(); } dp[len]=0; ll ans=0; for(int i=len-1;i>=0;i--)//因为匹配的成不成功,我们只能在后面看到,一开始只有(,没有办法判断, { if(pos[i]==-1) continue; dp[i]=dp[pos[i]+1]+1;
ans+=dp[i]; } printf("%I64d\n",ans); } return 0;} 当然我们也可以从前面开始向后面加//()()(),1 1 1,3 + 2 + 1,就像是 // 1 // 1 11 // 1 11 111 // 1 11 111 1111 //每次都是像这样不断出现新的,我们有规律可循
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <cstring> typedef long long ll; using namespace std; /* 竟然会超时,memset都会超时,简直了 */ char str[1100010]; ll dp[1100010]; int pos[1100010]; int main() { int T; scanf("%d",&T); while(T--) { scanf("%s",str); stack<int> stk; int len=strlen(str); for(int i=0;str[i];i++) { dp[i]=0; pos[i]=-1; if(str[i]=='(') { stk.push(i); continue; } if(stk.empty()) continue; int p=stk.top(); pos[i]=p;//记录( 的位置 stk.pop(); } dp[len]=0; ll ans=0; for(int i=0;i<len;i++) { if(pos[i]==-1) continue; if(pos[i]!=0) dp[i]=dp[pos[i]-1]+1; else dp[i]=1; ans+=dp[i]; } printf("%I64d\n",ans); } return 0; }