Codeforces 1015F Bracket Substring AC自动机 + dp
这么垃圾的题怎么以前都不会写啊, 现在一眼怎么就会啊。。。。
考虑dp[ i ][ j ][ k ][ op ] 表示 已经填了 i 个空格, 末尾串匹配到 所给串的 第 j 个, 已经放了 k 个左括号, 是否存在所给串的方案数。
因为不匹配的不是从头开始的, 所以暴力求下一个或者直接ac自动机都可以。
#include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 200 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;} struct Ac { int ch[N][26], f[N], tot, sz; int n, tar, dp[N][N][N][2]; char s[N]; inline int newNode() { tot++; f[tot] = 0; memset(ch[tot], 0, sizeof(ch[tot])); return tot; } void init(int _sz) {sz = _sz; tot = -1; newNode();} inline int idx(int c) {return c - '(';} void addStr(char* s) { int u = 0; for(int i = 0; s[i]; i++) { int c = idx(s[i]); if(!ch[u][c]) ch[u][c] = newNode(); u = ch[u][c]; } tar = u; } void build() { queue<int> que; for(int c = 0; c < sz; c++) { int v = ch[0][c]; if(!v) ch[0][c] = 0; else f[v] = 0, que.push(v); } while(!que.empty()) { int u = que.front(); que.pop(); for(int c = 0; c < sz; c++) { int v = ch[u][c]; if(!v) ch[u][c] = ch[f[u]][c]; else f[v] = ch[f[u]][c], que.push(v); } } } void solve() { init(2); scanf("%d", &n); scanf("%s", s); addStr(s); build(); dp[0][0][0][0] = 1; for(int i = 0; i < 2 * n; i++) { for(int u = 0; u <= tot; u++) { for(int c = 0; c <= n; c++) { for(int p = 0; p < 2; p++) { if(!dp[i][u][c]) continue; if(c <= n) { int v = ch[u][0]; add(dp[i + 1][v][c + 1][p || v == tar], dp[i][u][c][p]); } if(i - c < c) { int v = ch[u][1]; add(dp[i + 1][v][c][p || v == tar], dp[i][u][c][p]); } } } } } int ans = 0; for(int u = 0; u <= tot; u++) add(ans, dp[2 * n][u][n][1]); printf("%d\n", ans); } } ac; int main() { ac.solve(); return 0; } /* */