题意
给定一个长度为n 只包含左括号和右括号的序列,求每一个位置经过的合法子串有多少个。
空串是一个合法的串,如果A 和B 都是合法的串,那么(A) 和AB 都是合法的串。
令
ans[i]
为第
i
位的答案,对于每组数据,输出一个整数
n≤106
数据组数
T≤10
Time
Limits:1000ms
Memory
Limits:512M
分析
我们可以先用栈 处理出每对配对的括号(从左到右,左括号入栈,右括号弹出栈顶与之配对),然后用简单的递推计算即可。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
const LL P = 1e9 + 7;
int n,Inf;
int a[N],l[N],r[N];
int st[N],next[N],last[N];
char in[N];
LL ans,t[N];
void init() {
scanf(" %s",in + 1);
n = strlen(in + 1);
}
void pre() {
memset(st,0,sizeof(st));
memset(last,0,sizeof(last));
memset(next,0,sizeof(next));
int top = 0;
for (int i = 1;i <= n;i ++) if (in[i] == '(') st[++ top] = i;
else if (top) next[st[top]] = i + 1,last[i + 1] = st[top --];
}
void solve() {
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
memset(t,0,sizeof(t));
for (int i = n + 1; i >= 1;i --) {
r[i]++;
r[last[i]] += r[i];
}
for (int i = 1;i <= n;i ++) {
l[i]--;
l[next[i]] += l[i];
}
for (int i = 1;i <= n;i ++) t[i] = r[i] + l[i];
for (int i = 1;i <= n;i ++) t[i] += t[i-1];
LL ans = 0;
for (int i = 1;i <= n;i ++) ans += 1LL * i * t[i] % P;
printf("%lld\n",ans);
}
int main() {
int T;
scanf("%d",&T);
while (T --) {
init();
pre();
solve();
}
}