ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NC18413 括号 动态规划

2022-07-10 00:31:40  阅读:144  来源: 互联网

标签:方案 遍历 匹配 合法 括号 动态 NC18413 DP


链接:https://ac.nowcoder.com/acm/problem/18413
来源:牛客网

题目描述

小A有一个只包含左右括号的字符串S。但他觉得这个字符串不够美观,因为它不是一个合法的括号串。一个合法的括号串是这样定义的: 1. ()是合法的括号串 2. 若A是合法的括号串,则(A)则是合法的括号串 3. 若A,B是合法的括号串,则AB也是合法的括号串。
小A现在希望删掉S中若干个字符,使得剩下的字符串是一个合法的括号串。小A想知道有多少不同的方案。两个方案是不同的,当且仅当他们删除的位置不同。比如当S是(()时,有两种方案。分别是删掉第一个位置,或是删掉第二个位置。

输入描述:

第一行一个整数n,代表S的长度。
第二行输入n个字符,字符要么是(,要么是)。代表串S。

输出描述:

一行一个整数,代表不同的方案数。答案对10^9+7取模。
示例1

输入

复制
8
)(()(())

输出

复制
30

备注:

20%: n <= 20
40%: n <= 100
60%: n <= 1000
100%: n <= 10000

分析

首先,得确定是哪种DP,这题是计算完全匹配的方案数量,不是选择。但可以是区间DP,或者线性DP。

为什么不是区间DP,而是线性DP?

这道题的数据范围是1e5,n^2 显然不可能,那就只能是线性DP了

线性DP,随着字符串长度的变长,完全匹配的方案是在增加的,不匹配的左括号也是在增加的,不匹配的左括号的数目最多是多少呢?是当前遍历到的字符串长度。什么时候完全匹配的方案会增加呢?遇到右括号的时候。什么时候不匹配的左括号会增加呢?遇到左括号的时候。

假设f[i][j] 表示 遍历到第i个字符,总共有j个不匹配的左括号的方案数。

由于还没遍历数组的时候,是空集,方案合法,所以初值:f[0][0] = 1 

当遍历到左括号,不匹配的方案数增加,容易想到状态转移方程式:f[i][j] += f[i-1][j-1]

当遍历到右括号,匹配的方案数增加,容易想到状态转移方程是:f[i][j] += f[i-1][j+1]

更改遍历顺序能够压缩数组成一维:f[j] 表示 遍历到第i个字符,总共有j个不匹配的左括号的方案数

最后输出答案f[0] - 1(去掉空集,由例子知,该方案不合法)

代码

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N = 10005;
const ll mod = 1e9 + 7;
ll f[N]; //表示前i个字符中有j个左括号未配对成功的方案数
int n;
char s[N];

int main()
{
scanf("%d%s",&n,s+1);
f[0] = 1;
for(int i = 1;i<=n;i++) {
if(s[i] == '(') {
for(int j = n;j>=0;j--) {
if(j !=0 ) f[j] = (f[j] + f[j-1]) % mod;
}
} else {
for(int j = 0;j<=n-1;j++) {
f[j] = (f[j] + f[j+1]) % mod;
}
}
}
f[0] -- ;
cout<<f[0]<<endl;
}

标签:方案,遍历,匹配,合法,括号,动态,NC18413,DP
来源: https://www.cnblogs.com/er007/p/16462326.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有