题目传送门
题目描述:
Solution
我们考虑一对括号能够产生的贡献。
设
d
p
[
l
]
[
r
]
[
i
]
[
j
]
dp[l][r][i][j]
dp[l][r][i][j]表示当前区间为
[
l
,
r
]
[l,r]
[l,r],第
l
l
l个括号的颜色为
i
i
i,第
r
r
r个括号的颜色为
j
j
j的方案数。(
i
,
j
∈
[
0
,
1
,
2
]
i,j\in [0,1,2]
i,j∈[0,1,2])
我们设
m
a
t
[
i
]
mat[i]
mat[i]表示第
i
i
i个括号匹配到的右括号的位置(其中第
i
i
i个括号为左括号),这里我们需要用一个栈去操作:
接着对于问题在
[
l
,
r
]
[l,r]
[l,r]的区间,我们需要分类讨论:
1、
l
+
1
=
=
r
l+1==r
l+1==r,此时对应这种情况:
即只有一个合法括号对,这时候我们直接赋值:
注意,同一对括号有且只能有一种颜色,所以两种颜色都有的是无法更新的。
2、
m
a
t
[
l
]
=
=
r
mat[l]==r
mat[l]==r,此时对应这种情况:
(咳咳,中间的字符就不用管了)
这个时候,我们的答案是能够直接从
[
l
+
1
,
r
−
1
]
[l+1,r-1]
[l+1,r−1]这段区间转移过来的,直接类加上答案即可。需要注意的细节就是相邻的不能重复:
3、
m
a
t
[
l
]
!
=
r
mat[l]!=r
mat[l]!=r,即这种情况:
这种情况的时候我们需要先把两边的区间递归求解,然后再来合并答案。
这个时候有点麻烦,因为有四个括号,我们需要用四重循环分别取枚举每个括号的颜色,同时需要注意将重复的给判掉。
由于两个括号序列是独立的,所以是相乘。
分类讨论的情况我们结束了,接下来就是累加答案。
分别枚举
1
号
和
n
号
括
号
的
颜
色
1号和n号括号的颜色
1号和n号括号的颜色然后累加即可。
此时不判颜色也没关系,因为贡献就位0,当然判了也没关系。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e3+10,P = 1e9+7;
int n;
char s[N];
int dp[N][N][3][3];
int mat[N];
void Find(){
stack < int > q;
for (int i = 1; i <= n; i++)
if (s[i] == '(') q.push(i);
else mat[q.top()] = i,q.pop();
}
#define f dp[l][r]
#define f1 dp[l][mat[l]]
#define f2 dp[mat[l]+1][r]
#define f3 dp[l+1][r-1]
void dfs(int l,int r){
if (l + 1 == r){
f[0][1] = f[0][2] = f[1][0] = f[2][0] = 1;
return;
}
if (mat[l] == r){
dfs(l+1,r-1);
for (int i = 0; i <= 2; i++)
for (int j = 0; j <= 2; j++){
if (i!=1) f[1][0] = (f[1][0] + f3[i][j])%P;
if (i!=2) f[2][0] = (f[2][0] + f3[i][j])%P;
if (j!=1) f[0][1] = (f[0][1] + f3[i][j])%P;
if (j!=2) f[0][2] = (f[0][2] + f3[i][j])%P;
}
return;
}
dfs(l,mat[l]); dfs(mat[l]+1,r);
for (int il = 0; il <= 2; il++)
for (int jl = 0; jl <= 2; jl++)
for (int jr = 0; jr <= 2; jr++)
for (int ir = 0; ir <= 2; ir++){
if ((jl == jr) && jl != 0) continue;
f[il][ir] = (f[il][ir] + f1[il][jl] * f2[jr][ir])%P;
}
return;
}
signed main(){
scanf("%s",s+1);
n = strlen(s+1);
Find();
dfs(1,n);
int ans = 0;
for (int i = 0; i <= 2; i++)
for (int j = 0; j <= 2; j++) ans = (ans + dp[1][n][i][j])%P;
cout<<ans;
}