51nod 1791 合法括號子段

2022-07-26 10:18:14 字數 1529 閱讀 4230

有乙個括號序列,現在要計算一下它有多少非空子段是合法括號序列。

合法括號序列的定義是:

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

2.如果s是合法括號序列,那麼(s)是合法括號序列。

3.如果a和b都是合法括號序列,那麼ab是合法括號序列。

多組測試資料。

第一行有乙個整數t(1<=t<=1100000),表示測試資料的數量。

接下來t行,每一行都有乙個括號序列,是乙個由'('和')'組成的非空串。

所有輸入的括號序列的總長度不超過1100000。

輸出t行,每一行對應乙個測試資料的答案。

5(()

()()

(()(())

2013

12

對於判斷括號序列的合法性,有一種很簡潔的方法:

設左括號為-1,右括號為+1,求得乙個字首和陣列\(f\)。

那麼正確的括號序列必然是以-1開頭,0結尾,且中間的數都小於等於零。

知道了這個,此題還需要鍊錶+rmq操作

首先對於每乙個字首建乙個鍊錶\(nxt[f[i]]\)。

假設我們以i為括號序列起點,那麼它右邊的字首都得\(-f[i-1]\),那麼下乙個為0的位置是\(nex[f[i-1]]\),我們已經預處理它的位置

直接rmq查詢即可。誒,這樣好像也會超時,最壞情況下也是\(o(n^2)\)的,因為我們會沿著鍊錶跳很多次。。。

那麼就倒著做吧,我們記錄好以nex[i]為結尾的的答案,以後直接累加即可,至此,時間複雜度降為\(o(nlogn)\)

#include #include #include #include #include #include #include #include #include #define ll long long

#define inf 1000000000

#define pi acos(-1)

#define rep(i,x,n) for(ll i=x;i<=n;i++)

#define dep(i,n,x) for(ll i=n;i>=x;i--)

#define mem(a,x) memset(a,x,sizeof(a))

using namespace std;

ll read()

while(ch>='0'&&ch<='9')

return x*f;

}void out(ll a)

const int n=1100000+10;

char a[n];

int f[n];

mapfa;

mapvis;

int nxt[n];

int dp[n][20];

void rmq_init(int n)

vis[-1]=0;

for(int i=n;i>=1;i--)

ans+=vis[i-1];}}

printf("%lld\n",ans);

}return 0;

}

51nod 1791 合法括號子段

題解 我們可以發現每一對可以匹配的左右括號一定是一一對應的,那麼我們用乙個棧維護即可。如果當前是右括號,棧頂是左括號,那麼一定有1的貢獻,還要加上之前到達過top 1這個位置多少次,因為現在這一對括號可以和之前的那些組成更長的序列。1 include2 include3 include4 defin...

51nod 1791 合法括號子段 (dp)

有乙個括號序列,現在要計算一下它有多少非空子段是合法括號序列。合法括號序列的定義是 空序列是合法括號序列。如果 s 是合法括號序列,那麼 s 是合法括號序列。如果 a 和 b 都是合法括號序列,那麼 ab 是合法括號序列。多組測試資料。第一行有乙個整數 t 1 t 1100000 表示測試資料的數量...

51nod 1791 合法括號字段

原題連線 51nod 1791 合法括號字段 1791 合法括號子段 基準時間限制 1 秒 空間限制 131072 kb 分值 40 難度 4級演算法題 有乙個括號序列,現在要計算一下它有多少非空子段是合法括號序列。合法括號序列的定義是 1.空序列是合法括號序列。2.如果s是合法括號序列,那麼 s ...