題目鏈接
題意:
給你一個括號序列 和一個數 ,讓你求出長度爲 並且 是最後串裏面的一個子串的合法括號序列有多少種。。
分析:
先確定 表示最後的串到第 位,後綴匹配到長度爲 的原串,有 個未匹配的左括號的方案數有多少個。
爲什麼要這樣定義狀態呢,如果只是單純地定義 的話,你不能夠確定這些串裏面是否含有 (感覺是廢話)。
那麼轉移就是
但是這樣的轉移好像很麻煩,我們換成
是不是感覺很簡單,然後這個 當前位填 ‘(’ or ‘)’ 後對應的原串後綴長度 可以用 的 數組來優化,我直接預處理出來一個數組 表示當前串後綴已經和原串匹配了長度 ,接下來填 , 後,後綴和原串對應的匹配長度。然後就可以愉快的 了。
當匹配到長度和原串相同時,就直接轉移到 統計答案。
最後答案就是 。
代碼:
#include <bits/stdc++.h>
#include <ext/rope>
using namespace __gnu_cxx;
using namespace std;
#define mst(a,b) memset(a,b,sizeof(a))
#define ALL(x) x.begin(),x.end()
#define pii pair<int, int>
#define debug(a) cout << #a": " << a << endl;
#define eularMod(a, b) a < b ? a : a % b + b
inline int lowbit(int x){ return x & -x; }
typedef long long LL;
typedef unsigned long long ULL;
const int N = 1e5 + 10;
const long long mod = 1000000007;
const int INF = 0x3f3f3f3f;
const long long LINF = 0x3f3f3f3f3f3f3f3fLL;
const double PI = acos(-1.0);
const double eps = 1e-6;
char s[205];
int n;
int nex[205];
int to[205][2];
int dp[205][205][205];
int main() {
#ifdef purple_bro
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
scanf("%d%s", &n, s);
n <<= 1;
int len = strlen(s);
nex[0] = 0;
nex[1] = 0;
for (int i = 1; i < len; i++) {
int tmp = nex[i];
for (;tmp && s[tmp] != '(';)
tmp = nex[tmp];
to[i][0] = (s[tmp] == '(') ? tmp + 1 : 0;
tmp = nex[i];
for (;tmp && s[tmp] != ')';)
tmp = nex[tmp];
to[i][1] = (s[tmp] == ')') ? tmp + 1 : 0;
int j = nex[i];
for (;j && s[j] != s[i];)
j = nex[j];
nex[i + 1] = (s[i] == s[j]) ? j + 1 : 0;
}
for (int i = 1; i <= n; i++) {
if (i == 1) {
if (s[0] == '(')
dp[i][1][1] = 1;
else
dp[i][0][1] = 1;
continue;
}
for (int j = 0; j <= len && j < i; j++) {
for (int k = 0; k < i; k++) {
if (j < len) {
if (s[j] == '(')
(dp[i][j + 1][k + 1] += dp[i - 1][j][k]) %= mod;
else
(dp[i][to[j][0]][k + 1] += dp[i - 1][j][k]) %= mod;
if (s[j] == ')')
(dp[i][j + 1][k] += dp[i - 1][j][k + 1]) %= mod;
else
(dp[i][to[j][1]][k] += dp[i - 1][j][k + 1]) %= mod;
} else {
(dp[i][j][k + 1] += dp[i - 1][j][k]) %= mod;
(dp[i][j][k] += dp[i - 1][j][k + 1]) %= mod;
//只轉移到 len
}
}
}
}
printf("%d\n", dp[n][len][0]);
return 0;
}