【洛谷 1944】DP / 栈 / 玄学做法
题意:
(1) 空的括号序列是美观的;
(2) 若括号序列 A 是美观的,则括号序列(A)、[A]、{A}也是美观的;
(3) 若括号序列 A、B 都是美观的,则括号序列 AB 也是美观的;
例如 [(){}]() 是美观的括号序列,而 )({)[}]( 则不是。
现在所给的括号序列中,找出其中连续的一段,满足这段子序列是美观的,并且长度尽量大。
今天集训第一题就是它【洛谷1944】,只是换了一下输出,输出最长的美观的连续子序列的长度。
刚开始做的时候,还想着这是栈的经典例题,然后我就不知道为什么打了个队列,没错!!就是队列!! 我怕是石乐智了(两个样例还过了一个)!!!!陆陆续续调了一天!!!!!!这时候才想起来是栈。。。。。
还有一点:别忘了判断栈是否已经为空!!!!!!
题解:
- 方法一:栈
1 #include <cstdio> 2 #include <string> 3 #include <stack> 4 #include <iostream> 5 6 std::string s; 7 8 int ans, maxn; 9 10 void fs() { 11 std::stack<char> q; 12 int len = s.length(); 13 for (int i = 0; i < len; ) { 14 while (s[i] == '(' || s[i] == '[' || s[i] == '{') { 15 q.push(s[i++]); 16 } 17 18 if (s[i] == ')') { 19 if (!q.empty() && q.top() == '(') { // !!!!!判断是否栈空,为此我 RE 了 4 个点 20 q.pop(), ans += 2, i++; 21 if (maxn < ans) maxn = ans; 22 } else { 23 while (s[i] == ')' || s[i] == ']' || s[i] == '}') i++; 24 while (!q.empty()) q.pop(); 25 ans = 0; 26 } 27 } else if (s[i] == ']') { 28 if (!q.empty() && q.top() == '[') { 29 q.pop(), ans += 2, i++; 30 if (maxn < ans) maxn = ans; 31 } else { 32 while (s[i] == ')' || s[i] == ']' || s[i] == '}') i++; 33 while (!q.empty()) q.pop(); 34 ans = 0; 35 } 36 } else if (s[i] == '}') { 37 if (!q.empty() && q.top() == '{') { 38 q.pop(), ans += 2, i++; 39 if (maxn < ans) maxn = ans; 40 } else { 41 while (s[i] == ')' || s[i] == ']' || s[i] == '}') i++; 42 while (!q.empty()) q.pop(); 43 ans = 0; 44 } 45 } 46 } 47 48 } 49 50 int main() { 51 freopen("sequence.in", "r", stdin); 52 freopen("sequence.out", "w", stdout); 53 54 std::cin >> s; 55 56 fs(); 57 58 printf("%d\n", maxn); 59 return 0; 60 }
- 方法二:DP
1 #include <cstdio> 2 #include <string> 3 #include <iostream> 4 5 const int MAXN = 1000050; 6 7 std::string s; 8 9 int dp[MAXN], maxn = 0, max, t; // dp数组代表以第i个元素结尾的最长子序列长度
10 // 还有一种dp方法是dp[i]代表以第i个元素开头的最长子序列长度,从后向前dp 11 int main() { 12 freopen("sequence.in", "r", stdin); 13 freopen("sequence.out", "w", stdout); 14 15 std::cin >> s; 16 17 int len = s.length(); 18 19 for (int i = 0; i < len; i++) { 20 if (s[i] == '(' || s[i] == '[' || s[i] == '{') continue; 21 else if ((s[i] == ')' && s[i - 1 - dp[i - 1]] == '(') || (s[i] == ']' && s[i - 1 - dp[i - 1]] == '[') || ((s[i] == '}' && s[i - 1 - dp[i - 1]] == '{'))) { 22 dp[i] = dp[i - 1] + 2; 23 if (i - 2 - dp[i - 1] < 0) t = 0; // 防止越界 24 else t = dp[i - 2 - dp[i - 1]]; 25 dp[i] += t; 26 if (dp[i] > maxn) maxn = dp[i], max = i; 27 } 28 } 29 30 printf("%d\n", maxn); 31 32 33 return 0; 34 }
- 方法三:其实同方法一
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n, p, ans, len, f[100010]; 7 char s[100010]; 8 int main() { 9 freopen("sequence.in","r",stdin); 10 freopen("sequence.out","w",stdout); 11 scanf("%s", s); 12 n = strlen(s); p = 0; 13 for (int i = 0; i < n; i++) { 14 p = 0; 15 for (int j = i; j < n; j++) { 16 if (s[j] == '(') f[++p] = ')'; 17 else if (s[j] == '[') f[++p] = ']'; 18 else if (s[j] == '{') f[++p] = '}'; 19 else if (!p || s[j] != f[p]) break; 20 else { 21 p--; 22 if (!p) ans = max(ans, j - i + 1); 23 } 24 } 25 } 26 cout << ans << endl; 27 }

浙公网安备 33010602011771号