首页 > 其他分享 >题解 [CSP-S 2021] 括号序列

题解 [CSP-S 2021] 括号序列

时间:2023-10-03 14:44:12浏览次数:40  
标签:匹配 题解 合并 括号 枚举 2021 序列 CSP dp

题目链接

对于括号题,基本是栈匹配没有匹配的左括号和区间 \(dp\) 两个方向。这道题括号序列并不确定,只能用区间 \(dp\) 搞。

如果直接设 \(f_{l,r}\) 表示 \(l\sim r\) 的合法括号序列,那么由区间 \(dp\) 的套路可知,需要枚举中间点进行合并,那么 \(()()()\) 的情况就会出问题,原因是第一次将 \(()\) 与 \(()()\) 合并,第二次将 \(()()\) 和 \(()\) 进行合并,计算重复。

为了解决这个问题,我们规定只将 \(()()\) 与 \(()\) 进行合并,也就是先将括号序列分成两类,分别是 两边括号匹配,和两边括号不匹配,计作 \(f,g\),那么合并时将 \(f\) 合并到 \(g\) 上即可。接下来推 \(dp\) 方程。

判断连续段能否被完全填充,可以采取前缀和的方式,若一段内 \(?,*\) 的总和等于段长且不超过给定数量。

左右括号能匹配的:

\(()\):长度为 \(2\),将 \(f_{i,i+1}+1\) 即可。
\((S)\):若中间可以由连续的 \(*\) 填充,则将 \(f_{l,r}+1\)。
\((SA)\):枚举 \(S\) 的断点 \(k\),那么 \(f_{l,r}=f_{k+1,r}+g_{k+1,r}\)。
\((AS)\):枚举 \(S\) 的断点,\(f_{l,r}=f_{l,k-1}+g_{l,k-1}\)

左右括号不能匹配的:

\(AB\):令 $B=f,枚举断点 \(k\),那么 \(g_{l,r}=(g_{l,k}+f_{l,k})\times f_{k+1,r}\)。

\(ASB\):可以先处理出 \(B=f\) 的 \(SB\) 数量,计作 \(h\),然后用 \(h\) 更新 \(g\),\(g_{l,r}=(f_{l,k}+g_{l,k}) \times h_{k+1,r}\)

代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
#define PII pair<int,int>
LL read() {
	LL sum=0,flag=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') flag=-1; c=getchar();}
	while(c>='0'&&c<='9') {sum=sum*10+c-'0'; c=getchar();}
	return sum*flag;
}

const int N=510;
const LL MOD=1e9+7;
int n,m;
int sum[N];
string s;
LL f[N][N],g[N][N],h[N][N];
//合法,左右括号匹配,左右括号不匹配,SA的数量

int pd(int l,int r) {
	if(sum[r]-sum[l-1]<=m&&sum[r]-sum[l-1]==r-l+1) return 1;
	else return 0;
}

int check(int l,int r) {
	if(s[l]=='('&&s[r]==')') return 1;
	if(s[l]=='?'&&s[r]==')') return 1;
	if(s[l]=='('&&s[r]=='?') return 1;
	if(s[l]=='?'&&s[r]=='?') return 1;
	return 0;
}

int main() {
	cin>>n>>m;
	cin>>s; s=" "+s;
	for(int i=1;i<=n-1;i++) {
		if(s[i]=='?'||s[i]=='*') sum[i]=sum[i-1]+1;
		else sum[i]=sum[i-1];
		if(check(i,i+1)) f[i][i+1]=1;
	}
	for(int len=3;len<=n;len++){
		for(int i=1;i+len-1<=n;i++) {
			int j=i+len-1;
			if(check(i,j)) {
				if(pd(i+1,j-1)) f[i][j]=(f[i][j]+1)%MOD;
				for(int k=i+1;k<=j-1;k++) {
					if(pd(i+1,k)) f[i][j]=(f[i][j]+f[k+1][j-1]+g[k+1][j-1])%MOD;
				}
				for(int k=j-1;k>=i+1;k--) {
					if(pd(k,j-1)) f[i][j]=(f[i][j]+f[i+1][k-1]+g[i+1][k-1])%MOD;
				}
				f[i][j]=(f[i][j]+f[i+1][j-1]+g[i+1][j-1])%MOD;
			}
			for(int k=i;k<=j;k++) {
				g[i][j]=(g[i][j]+(f[i][k]+g[i][k])*f[k+1][j])%MOD;
			}
			for(int k=i;k<=j;k++) {
				if(pd(i,k)) h[i][j]=(h[i][j]+f[k+1][j])%MOD;
			}
			for(int k=i;k<=j;k++) {
				g[i][j]=(g[i][j]+(g[i][k]+f[i][k])*h[k+1][j]%MOD)%MOD;
			}
		}
	}
	cout<<(f[1][n]+g[1][n])%MOD;

	return 0;
}

标签:匹配,题解,合并,括号,枚举,2021,序列,CSP,dp
From: https://www.cnblogs.com/zhangyuzhe/p/17740980.html

相关文章

  • 【UVA 12100】Printer Queue 题解(队列+优先队列)
    计算机科学学生会中唯一的打印机正经历着极其繁重的工作量。有时,打印机队列中有100个作业,您可能需要等待数小时才能获得一页输出。由于某些作业比其他作业更重要,黑客将军为打印作业队列发明并实现了一个简单的优先级系统。现在,为每个作业分配1到9之间的优先级(9是最高优先级,1是最低......
  • [题解]CF1748C Zero-Sum Prefixes
    UPD23.10.3更新的对思路的描述,以及代码。思路对于每一个\(a_i=0\),如果我们将它变为\(x\),都可以直接将\(i\simn\)位置上的前缀和加\(x\)。设\(a_j\)是\(a_i\)后第一个\(0\),那么,在\(j\)时同样有上述规律。所以,我们只需在\(i\)时考虑,\(i\sim(j-1)\)的贡......
  • 题解 [蓝桥杯 2016 省 B] 交换瓶子
    题目链接本题解讲解环图的做法。要将一个\(1\simn\)的排列通过交换变成\(1\simn\),可以先将\(i\)向\(a_i\)连边,那么最终一定会练成若干个环(每个点只有一个出度,也只有一个入度)。假设交换在同一个环中的节点,一个环显然会变成两个环,也就是说,交换一次最多增加一个环的数量,......
  • 【题解】洛谷 P1003 [NOIP2011 提高组] 铺地毯
    原题链接解题思路如果直接按照题意开一个二维数组来模拟每个点最上面的地毯编号,会发现所占空间最坏情况下约为(2*105)2*4B=4*1010*4B=1.6*1011B≈149GB,程序完全无法运行。但实际上没有必要将每一个点的信息记录下来,只需要记录每一块地毯能覆盖哪些点,再依次判断哪那些地毯可以......
  • 「题解」Codeforces Round 894 (Div. 3)
    A.GiftCarpetProblem题目Sol&Code签到题#include<bits/stdc++.h>#defineN21typedeflonglongll;intmin(inta,intb){returna<b?a:b;}intmax(inta,intb){returna>b?a:b;}intT,n,m,a[4];std::strings[N];i......
  • T2回家(home)题解
    T2回家(home)现在啥也不是了,虽然会了逆元,但是对期望概率题还是一窍不通,赛时相当于只推出了\(n=1\)的情况,结果运用到所有情况,理所应当只有20分。题目描述小Z是个路痴。有一天小Z迷路了,此时小Z到家有NN个单位长度。小Z可以进行若干次行动,每次行动小Z有\(\frac12\)的概率向......
  • abaqus下载 - abaqus(有限元软件)v2021免费版 安装包下载方式
    Abaqus2019是一款广泛使用的有限元分析软件,它提供了强大的建模和分析工具,可以帮助用户进行各种复杂结构的力学仿真分析。以下是Abaqus2019的主要特点:软件地址:看置顶贴软件特色一、接触和约束1.接触和约束概览2.Abaqus/Standard中的边-边接触二、材料1.材料概览2.并行流变框架(PRF......
  • [ARC035B] アットコーダー王国のコンテスト事情 题解
    前置芝士排列组合分析明显的贪心,第一问与此题思路相似,优先选择做时间少的,可以尽可能让后面的罚时尽量的小。难点在第二问,第二问问的是有几种可能性,有个显然的结论:相同做题时间的题目,位置调换答案仍然相同。那么可以用桶+排列组合来解决:用桶储存这个做题时间的出现次数\(b......
  • AT_abc321_f 题解
    #思路简单动态规划,$dp_i$指当前操作后取和为$i$的球的方案数,每次输出$dp_K$即可。需要注意的是对于每次`+x`操作,计算$dp$数组时要倒着循环。时间复杂度:$O(QK)$。#代码```cpp#include<bits/stdc++.h>usingnamespacestd;longlongdp[5010];intmain(){ longlon......
  • RDP远程登录后全屏,本地的任务栏始终显示的问题解决
    文章目录问题解决参考问题RDP远程登录后全屏,本地的任务栏(TaskBar)始终在下面,遮住了远程桌面的最下面,进行了解决。解决BestsolutionhowtohidelocalTaskbarwhenRDPtoaremotedesktopLaunchTaskManagerRight-click“WindowsExplorer”Select“Restart”Itworkson......