b_51_合法括号字段(栈+逆推)

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

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

思路:用栈记录每一个左括号的位置,r数组记录左括号对应的最近右括号的位置
递推过程:当遇到左括号时,若存在对应的右括号,则f[i]=f[r[i]+1]+1,代表i位置的合法括号字段多了一个
r[i]+1:因为r[i]+1可能就是后面一个合法括号字段的开始,对应已满第3点

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1100005;
ll f[N],r[N];
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int t; cin>>t;
    while (t--) {
        string s; cin>>s;
        ll n=s.size(),ans=0; fill(f,f+n,0), fill(r,r+n,-1);
        stack<int> st;
        for (int i=0; i<n; i++) {
            if (s[i]=='(') st.push(i);
            else if (!st.empty()) r[st.top()]=i, st.pop();
        }
        for (int i=n-1; ~i; i--) {
            if (r[i]!=-1) f[i]=f[r[i]+1]+1;
            else f[i]=0;
            ans+=f[i];
        }
        cout<<ans<<'
';
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wdt1/p/13903272.html