1. 程式人生 > >最長括號匹配_NOI導刊2009提高 字串dp

最長括號匹配_NOI導刊2009提高 字串dp

題目描述
對一個由(,),[,]括號組成的字串,求出其中最長的括號匹配子串。具體來說,滿足如下條件的字串成為括號匹配的字串:
1.(),[]是括號匹配的字串。
2.若A是括號匹配的串,則(A),[A]是括號匹配的字串。
3.若A,B是括號匹配的字串,則AB也是括號匹配的字串。
例如:(),[],([]),()()都是括號匹配的字串,而](則不是。
字串A的子串是指由A中連續若干個字元組成的字串。
例如,A,B,C,ABC,CAB,ABCABCd都是ABCABC的子串。空串是任何字串的子串。
輸入輸出格式
輸入格式:

輸入一行,為一個僅由()[]組成的非空字串。

輸出格式:

輸出也僅有一行,為最長的括號匹配子串。若有相同長度的子串,輸出位置靠前的子串。

輸入輸出樣例
輸入樣例#1: 複製
([(][()]]()
輸出樣例#1: 複製
[()]
輸入樣例#2: 複製
())[]
輸出樣例#2: 複製
()

考慮 dp [ i ] 表示 以 i 位置開始的字串能匹配的最長長度,
自然從後往前遍歷;
那麼考慮題目中的條件;
有兩個轉移方程:

** dp[ i ] = dp[ i-1 ]+2 **

dp[ i ]+=dp[ i+dp[ i ] ]

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include
<cstring>
#include<string> #include<cmath> #include<map> #include<set> #include<vector> #include<queue> #include<bitset> #include<ctime> #include<deque> #include<stack> #include<functional> #include<sstream> #include<cctype>
//#pragma GCC optimize("O3") using namespace std; #define maxn 200005 #define inf 0x3f3f3f3f #define INF 0x7fffffff typedef long long ll; typedef unsigned long long ull; typedef unsigned int U; #define ms(x) memset((x),0,sizeof(x)) const long long int mod = 1e9 + 7; #define Mod 20100403 #define sq(x) (x)*(x) #define eps 1e-15 const int N = 2500005; inline int rd() { int x = 0; char c = getchar(); bool f = false; while (!isdigit(c)) { if (c == '-') f = true; c = getchar(); } while (isdigit(c)) { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); } return f ? -x : x; } ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); } string dat; int dp[maxn << 3]; int main() { ios::sync_with_stdio(false); cin >> dat; int id = 0; for (int i = dat.length()-1; i >= 0; i--) { if (dat[i] == ')' || dat[i] == ']')continue; if ((dat[i + dp[i + 1] + 1] == ')'&&dat[i] == '(') || (dat[i + dp[i + 1] + 1] == ']'&&dat[i] == '[')) { dp[i] = dp[i + 1] + 2; dp[i] += dp[i + dp[i]]; if (dp[i] >= dp[id]) { id = i; } } } for (int i = 0; i < dp[id]; i++) { cout << dat[id + i]; } cout << endl; return 0; }