【HDU5357】Easy Sequence 题解(栈的应用)

新博客:debug18.com 使用hexo搭建,欢迎来踩~

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5357


题目大意:给你一个括号序列(不保证合法),求对于每个字符,包含这个字符的合法括号序列的总方案数。


容易发现,对于一个匹配的括号“(...)”,其里面的内容对其总方案数并无影响,必须全部包括,所以只用考虑外面的。

其覆盖方案分为两种类型:

例子:"...()(...()()()...)()..." (根据合法序列是否覆盖了“包括了的最小的括号对”进行分类)

  • 第一部分:倘若的合法序列覆盖了整个括号对,那么这一部分的方案数等于括号对的总方案数
  • 第二部分:倘若的合法序列在括号对内,那么这种合法序列一定覆盖了其两边有与其“同级别"(即互不包含)的括号对,设左边有a个,右边有b个,则这一部分的方案数为 (a + 1) * (b + 1)

 合并在一起就求出了每个位置的方案数

做法:计算出第 i 个括号的匹配括号位置 match[i],包含它的括号对的左括号位置 pre[i],以及:

  • 对于左括号,其右边的“同级别”的括号个数(包括自己)forward[i] = forward[match[i]+1] + 1
  • 对于右括号,其左边的“同级别”的括号个数(包括自己)backward[i] = backward[match[i]-1] + 1

其中,match[i] 和 pre[i] 可以对序列用栈扫一遍求出,具体做法是:遇到左括号压进栈,遇到右括号就弹栈,之前的栈顶元素与当前元素相互 match,现在的栈顶元素成为当前元素及其 match 的 pre。

最后,ans[i] = ans[match[i]] = ans[pre[i]] + forward[i] * backward[match[i]]


我模板里的输出优化写丑了,导致一直WA……

代码:

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <cctype>
  6 #include <cassert>
  7 #include <ctime>
  8 #include <algorithm>
  9 #include <utility>
 10 #include <functional>
 11 
 12 #define X first
 13 #define Y second
 14 #define MP make_pair
 15 #define BP push_back
 16 #define SZ(x) ((int)(x).size())
 17 #define ALL(x) (x).begin(), (x).end()
 18 #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
 19 
 20 using namespace std;
 21 
 22 typedef long long LL;
 23 typedef long double LD;
 24 typedef pair<int, int> Pii;
 25 
 26 const int oo = 0x3f3f3f3f;
 27 
 28 template<class T> T read(T &x)
 29 {
 30     int f = 1;
 31     char ch = getchar();
 32     while (!isdigit(ch)) {
 33         if (ch == '-')
 34             f = -1;
 35         ch = getchar();
 36     }
 37     for (x = 0; isdigit(ch); ch = getchar())
 38         x = 10 * x + ch - '0';
 39 
 40     return x *= f;
 41 }
 42 template<class T> void write(T x)
 43 {
 44     if (x < 0) {
 45         putchar('-');
 46         x = -x;
 47     }
 48     static char s[20];
 49     int top;
 50     for (top = 0; x; x /= 10)
 51         s[++top] = x % 10 + '0';
 52     if (top == 0)
 53         putchar('0');
 54     else while (top)
 55         putchar(s[top--]);
 56 }
 57 // End of template
 58 
 59 const int MAXN = 1e6 + 5, MOD = 1e9 + 7;
 60 int N;
 61 char S[MAXN];
 62 
 63 int match[MAXN], pre[MAXN];
 64 void getMatch()
 65 {
 66     static int st[MAXN];
 67     int top = 0;
 68     memset(match, 0, sizeof(int) * (N + 1));
 69     memset(pre, 0, sizeof(int) * (N + 1));
 70     for (int i = 1; i <= N; i++) {
 71         if (S[i] == 0)
 72             st[++top] = i;
 73         else if (top) {
 74             match[st[top]] = i;
 75             match[i] = st[top];
 76             top--;
 77             if (top)
 78                 pre[match[i]] = st[top];
 79         }
 80     }
 81 }
 82 
 83 LL solve()
 84 {
 85     static int forward[MAXN], backward[MAXN], ans[MAXN];
 86     
 87     memset(forward, 0, sizeof(int) * (N + 2));
 88     for (int i = N; i; i--) {
 89         if (S[i] == 0 && match[i])
 90             forward[i] = forward[match[i]+1] + 1;
 91     }
 92     memset(backward, 0, sizeof(int) * (N + 2));
 93     for (int i = 1; i <= N; i++) {
 94         if (S[i] == 1 && match[i])
 95             backward[i] = backward[match[i]-1] + 1;
 96     }
 97     
 98     LL res = 0;
 99     memset(ans, 0, sizeof(int) * (N + 2));
100     for (int i = 1; i <= N; i++) {
101         if (S[i] == 0 && match[i])
102             ans[i] = ans[match[i]] = (ans[pre[i]] + (LL)forward[i] * backward[match[i]] % MOD) % MOD;
103         res += (LL)i * ans[i] % MOD;
104     }
105     return res;
106 }
107 
108 int main()
109 {
110 #ifndef ONLINE_JUDGE
111     freopen("tmp.in", "r", stdin);
112     freopen("tmp.out", "w", stdout);
113 #endif
114     int T;
115     read(T);
116     while (T--) {
117         scanf("%s", S + 1);
118         N = strlen(S + 1);
119         for (int i = 1; i <= N; i++)
120             S[i] = S[i] == ')';
121         getMatch();
122         write(solve()); putchar('\n');
123     }
124     
125     return 0;
126 }

 

posted on 2015-08-10 14:14  __debug  阅读(651)  评论(0编辑  收藏  举报

导航