棧+括號配對 51Nod1478 括號序列的最長合法子段
阿新 • • 發佈:2019-02-10
題意:給一字串只有括號,問最長合法子串的長度是多少,並輸出這樣的長度的子串有多少個。
思路:啊。。我發現這種括號配對的題我總是處理不好。
一開始想到了一種比較腦殘的方法,首先(代表+1,)代表-1,我們維護字首和s,然後我們用單調棧來維護最左端的滿足[x,i]所有字首和都>=s。
然後,我們並不能一直擴充套件到最左邊,我們還應該記錄字首和等於s且後一個字元是(的位置。因為我們對於一個),向左匹配最多也只能匹配到這個位置。
於是,就有了下面這段傻逼程式碼
#include <map> #include <set> #include <cmath> #include <ctime> #include <stack> #include <queue> #include <cstdio> #include <cctype> #include <bitset> #include <string> #include <vector> #include <cstring> #include <iostream> #include <algorithm> #include <functional> #define fuck(x) cout<<"["<<x<<"]"; #define FIN freopen("input.txt","r",stdin); #define FOUT freopen("output.txt","w+",stdout); //#pragma comment(linker, "/STACK:102400000,102400000") using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef long long LL; const int MX = 1e6 + 5; const int MID = MX; char S[MX]; int pos[2 * MX]; int Stack[MX], z[MX], ssz; int main() { //FIN; scanf("%s", S + 1); int n = strlen(S + 1), now = 0; memset(pos, -1, sizeof(pos)); Stack[++ssz] = 0; z[ssz] = 0; int maxlen = 0, cnt = 1; for(int i = 1; i <= n; i++) { if(S[i] == '(') now++; else now--; int p = i; while(ssz && now <= Stack[ssz]) p = z[ssz--]; Stack[++ssz] = now; z[ssz] = p; if(S[i] == ')' && pos[now + MID] != -1) { int len = i - max(pos[now + MID], p); if(len > maxlen) { maxlen = len; cnt = 1; } else if(len == maxlen) cnt++; } else if(S[i] == '(' && pos[now + MID - 1] == -1) { pos[now + MID - 1] = i - 1; } } printf("%d %d\n", maxlen, cnt); return 0; }
然後看了一下排行榜裡別人的做法,實在是太簡單易懂了~
我們來使用棧來匹配括號。如果為(,就壓入棧。如果為),就取出棧頂,此時,從當前的位置,到棧頂表示的(的位置,這整個子串,一定是合法的。
然後如果在(的前面也有一段合法括號,那麼兩段就能合在一起,形成更長的。
所以程式碼非常簡單,一個普通的棧,再加一個dp陣列記錄一下就ok了
啊,,下次再不會做括號匹配的題就藥丸了#include <map> #include <set> #include <cmath> #include <ctime> #include <stack> #include <queue> #include <cstdio> #include <cctype> #include <bitset> #include <string> #include <vector> #include <cstring> #include <iostream> #include <algorithm> #include <functional> #define fuck(x) cout<<"["<<x<<"]"; #define FIN freopen("input.txt","r",stdin); #define FOUT freopen("output.txt","w+",stdout); //#pragma comment(linker, "/STACK:102400000,102400000") using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef long long LL; const int MX = 1e6 + 5; char S[MX]; int Stack[MX], dp[MX], ssz; int main() { //FIN; scanf("%s", S + 1); int n = strlen(S + 1); int maxlen = 0, cnt = 1; for(int i = 1; i <= n; i++) { if(S[i] == '(') Stack[++ssz] = i; else if(ssz) { int t = Stack[ssz--]; dp[i] = dp[t - 1] + i - t + 1; if(dp[i] > maxlen) maxlen = dp[i], cnt = 1; else if(dp[i] == maxlen) cnt++; } } printf("%d %d\n", maxlen, cnt); return 0; }