您的位置:首页 > 其它

CSUST选拔赛题解之-Problem G: 括号匹配

2018-03-18 17:33 351 查看

Problem G: 括号匹配

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 45  Solved: 14
[Submit][Status][Web Board]

Description

给出一个字符串s,由'(',')'和'?'组成,'?'可以变成'('或')'.问最后这个字符串最后有多少种完美匹配。
完美匹配指任意一个')'都有一个相对应的'('与之匹配,如“()”,“(())”,“()()”。而“()(”不合法。

Input

第一行一个数T(T<=20)表示数据组数
接下来T行为,每行一个字符串s(s的长度<=3000);

Output

输出匹配的种类,答案可能很大,最后取值要mod(1e9+7)

Sample Input

4
??????
((()))()
??()??
((?))

Sample Output

5
1
2
0

HINT

第三个样例为“()()()”,“((()))”两种

解题思路:比赛完,学长告诉我们这是一道dp题,在补题时我想了两天还是没思路,最后请教了下我们的王逸峰大佬才会这一题,真的是不看题解不会dp啊,实在是菜得不要不要的 ╯△╰。。。AC代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<time.h>
#include<map>
#include<string>
#include<algorithm>
#include<set>
#include<queue>
#define N 100005

const int mod = 1000000007;

using namespace std;

char str[3010];
long long dp[3010][3010];
//这是从后往前dp,你也可以从前往后dp
long long Dp(int i, int j)
{  //表示在剩余i个括号的情况下,还需要j个左括号(注意i >= j和j > 0这两个条件)
if(i == 0 && j == 0) //匹配成功
return 1;
if(i == 0 && j != 0)
return 0;
if(dp[i][j] != -1) //记忆化,不然会TLE
return dp[i][j];
if(str[i-1] == '?'){
if(j - 1 < 0) {
dp[i][j] = Dp(i-1, j+1) % mod;
}
else if(i-1 < j+1) {
dp[i][j] = Dp(i-1, j-1) % mod;
}
else {
dp[i][j] = (Dp(i-1, j-1) + Dp(i-1, j+1)) % mod;
}
}
if(str[i-1] == '(') {
if(j-1 < 0) return 0;
else dp[i][j] = Dp(i-1, j-1) % mod;
}
if(str[i-1] == ')') {
if(i-1 < j+1) return 0;
else dp[i][j] = Dp(i-1, j+1) % mod;
}
return dp[i][j] % mod;
}

int main()
{
int T;
scanf("%d", &T);
while(T--)
{
memset(dp, -1, sizeof(dp));
scanf("%s", str);
if(strlen(str) % 2 != 0)
printf("0\n");
else
printf("%lld\n", Dp(strlen(str), 0) % mod);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: