括号序列

括号序列

代码如下

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxS = 5005;

string s;
int n;
ll f[maxS][maxS];

ll cal()
{
    memset(f,0,sizeof f);
    f[0][0] = 1;
    for(int i=0;i<s.size();i++)
    {
        if(s[i]=='(')
        {
            for(int j=1;j<=n;j++)
                f[i+1][j] = f[i][j-1];
        }else
        {
            f[i+1][0] = (f[i][0] + f[i][1])%mod;
            for(int j=1;j<=n;j++)
                f[i+1][j] = (f[i+1][j-1] + f[i][j+1])%mod;
        }
    }


    for(int j=0;j<=n;j++)
        if(f[n][j]) return f[n][j];
}
int main()
{
    cin >> s;
    n = s.size();
    ll l = cal();

    reverse(s.begin(),s.end());
    for(int i=0;i<s.size();i++)
        if(s[i]=='(')   s[i] = ')';
        else    s[i] = '(';
    ll r = cal();

    ll ans = l*r%mod;
    cout << ans << endl;
    return 0;
}

分析(来自y总):
关键词:理解+dp

1.序列合法,①'('数量=')'数量②那么任意一个前缀中'('的数量大于')'

——>(与题无关) cnt计数,'('+1 '')'-1,一旦cnt<0则一定要添左括号

2.本质不同 and 加左括号和有括号独立
e.g _(_(_(_)_	_是可插入的地方
关于括号的独立:
假设先添左括号_( 【(】 ( 【(】 (_)_,再添右括号
①右括号与添加的(在不同位置显然独立
②在同一位置如_( 【)(】 ( 【(】 (_)_只能是)(。因为若是()显然就本质相同了,因为这么一填对原序列无影响,换个意思说填不填()都没关系。

3.插入左括号和插入右括号本质相同,将序列翻转后,每个字符也翻转即可。((()填右括号相当于()))填左括号。
所以总方案数=左*右 = 左*右翻转
所以只考虑填左括号方案数就行

4.关于dp[i][j]
i表示第i个字符,j表示左括号比右括号多j,值表示方案数。(这些方案总是合法的,插入多少个(不管,只看结果)
答案为dp[n][0]-dp[n][n]中第一个非0的,因为此刻最小合法
(个人理解:一个序列不知道要填多少个(,但范围显然是0-n。()))添加到最后为了合法j显然为0,而((()为2,所以j也是0-n,而越靠近0添加也就越少,方案数应该越少)

就把)当成隔板(①【)】②【)】③【)】④就形成4个区域,在里面插入左括号顺序无关。最后总的方案数相当于4个区域(的数量,比如此时是1 0 0 0
所以转态转移方程
(:dp[i][j] = dp[i-1][j-1]	因为前面到这里刚好+1个(,而且(前面不能加'('(为了保障唯一性)
):dp[i][j] = dp[i-1][0] + dp[i-1][1] + ... + dp[i-1][j+1]	因为这里划分假设前面加了j+1-0个括号,又因为本身是),所以j前面对应0-j+1
又dp[i-1][0] + dp[i-1][1] + ... + dp[i-1][j] = dp[i][j-1]
所以dp[i][j]= dp[i][j-1] + dp[i-1][j+1];
注意dp[i][0] = dp[i-1][0]	+ dp[i-1][1];

dp[0][0] = 1
e.g()))填左括号,i是行,j是列
		0	1	2	3	4	
	0	1	0	0	0	0
	1	0	1	0	0	0	
	2	1	1	1	1	1
	3	2	3	4	5	5
	4	5	9	14	19	19

感觉自己写得乱七八糟的,将就看下吧,下面几个连接感觉讲得比我清楚,交叉补充看吧:
AcWing 3420. 括号序列(蓝桥杯C++ AB组辅导课) - AcWing
AcWing 3420. 括号序列(如果一直没能理解这道题,就进来看看这个吧) - AcWing
2021蓝桥杯省赛J:括号序列-思维+动态规划_括号序列题解b3758-CSDN博客

没做出来原因:
我做出来就有鬼了

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值