题意:
给定n和一个括号序列 t,问:一个长度为2*n 的括号序列 s 的种类数,要求 t 是 s 的子串,s是平衡括号序列;
思路:
这个题算是 BZOJ - 1009: [HNOI2008]GT考试 dp+KMP https://blog.csdn.net/xiang_6/article/details/81434904
的简化版本; 解释一下这个题:
首先我们不考虑是否是平衡括号序列这个要求,如果只是要求 包含 t 的 s 的种类的话,我们可以
令 dp[i][j] 表示 当匹配到 s 串的第 i 个字符的时候,恰好匹配到 t 串的第 j 个字符,并且此时 s 串包含 j 个字符的后缀恰好是 t 串的前缀;这是dp[i][j] 就是上述条件下的种类数,再看状态转移
当我们要继续匹配 s 串第 i+1个字符时,对于本题,只有 ‘(’ ,‘)’ 两种情况,然后我们假设加上第 i+1个字符后,恰好匹配到了 t 串的第x个位置(这里的匹配是满足上述dp[][] 的定义的匹配),这样的话,dp[i][j] 就为 dp[i+1][x] 做出来贡献,
所以转移方程就是 dp[i+1][x] += dp[i][j] 这里的 x 由当前位置 j 和新加入的字符决定;这个 x 可以用KMP快速实现得到;
需要注意:当dp[i][j] 中 j = len(t 串长度) 时,无论添加什么字符,我们都仍然往 dp[i+1][len] 转移
然后我们考虑 s 是否是平衡括号序列的问题:
只需要再添加一维,令 dp[i][j][k], 前两维还是上述的 dp[i][j],,第三维表示当前括号序列中,除去平衡括号外,左括号多出来的数目为k,因为从左往右添加括号,右括号不能超过左括号,所以 k >=0, 转移方程改为:
当新加括号为'(' 时: dp[i+1][x][k+1] += dp[i][j][k]
当新加括号为'(' 并且 k>0 时: dp[i+1][x][k-1] += dp[i][j][k]
同时也要注意:j = len 时,这一行上面的两行转移方程中 x 一直为len;
还要注意一点:k 的大小我们更新到初始的n值就够了,否则会超时
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 200 + 7;
const int mod = 1e9 + 7;
int n, len, m;
char t[maxn];
int f[maxn], dp[maxn][maxn][maxn] = {0};
int main() {
scanf("%d%s", &n, t+1);
m = n; n <<= 1;
len = strlen(t+1);
f[1] = f[2] = 1;
for(int i = 2; i < len; ++i) {
int j = f[i];
while(j > 1 && t[j] != t[i]) j = f[j];
f[i+1] = (t[j] == t[i] ? j+1 : 1);
}
dp[0][0][0] = 1;
for(int i = 0; i < n; ++i) {
for(int j = 0; j <= len; ++j) {
for(int k = 0; k <= m; ++k) {
if(j == len) {
(dp[i+1][j][k+1] += dp[i][j][k] ) %= mod;
if(k) (dp[i+1][j][k-1] += dp[i][j][k] ) %= mod;
continue;
}
char c = '(';
int j_ = j+1;
while(j_ > 1 && t[j_] != c) j_ = f[j_];
if(t[j_] != c) j_--;
(dp[i+1][j_][k+1] += dp[i][j][k] ) %= mod;
if(k) {
char c = ')';
int j_ = j+1;
while(j_ > 1 && t[j_] != c) j_ = f[j_];
if(t[j_] != c) j_--;
(dp[i+1][j_][k-1] += dp[i][j][k] ) %= mod;
}
}
}
}
//for(int i = 0; i <= n; ++i) {
cout << dp[n][len][0] << endl;
//}
return 0;
}
/*
.::::.
.::::::::.
::::::::::: I want to say...Accepted!
..:::::::::::'
'::::::::::::'
.::::::::::
'::::::::::::::..
..::::::::::::.
``:::::::::::::::·
::::``:::::::::' .:::.
::::' ':::::' .::::::::.
.::::' :::: .:::::::'::::.
.:::' ::::: .:::::::::' ':::::.
.::' :::::.:::::::::' ':::::.
.::' ::::::::::::::' ``::::.
...::: ::::::::::::' ``::.
```` ':. ':::::::::' ::::..
'.:::::' ':'````..
******************** 美↑女坐键↓盘 ********************
┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐
│Esc│ │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│ ┌┐ ┌┐ ┌┐
└───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘ └┘ └┘ └┘
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐
│~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │N L│ / │ * │ - │
├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤
│ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │ │
├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │
│ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter │ │ 4 │ 5 │ 6 │ │
├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐ ├───┼───┼───┼───┤
│ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │
├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││
│ Ctrl│ │Alt │ Space │ Alt│ │ │Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│
└─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘
*/