CF1015F Bracket Substring(动态规划)

天涯浪子 提交于 2020-02-11 15:46:18

CF1015F Bracket Substring

这题一眼GT考试

题意: 求有多少种合法的括号序列要求字符串S是其字串

数据范围大概是一个\(\Theta(n^3)\)的算法

从前往后填括号, 设\(F[i][j][k]\)表示填到第\(i\)位, "和"为\(j\), 匹配了\(S k\)位, 其中和的定义为将左括号看做1, 右括号看作-1, 一个合法的括号序列的前缀和总大于等于零且本身的和为零(一个左括号一定匹配一个右括号)

\(dp\)时只需枚举下一位填\('('\)\(')'\)即可, 但要注意的是匹配\(S\)串时从第\(k\)位不匹配不是直接重新从0开始匹配而是求出它的\(kmp\)数组, 找到上一个\(border\), 可以参考代码

#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;

template <typename T>
void read(T &x) {
    x = 0; bool f = 0;
    char c = getchar();
    for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
    for (;isdigit(c);c=getchar()) x=x*10+(c^48);
    if (f) x=-x;
}

template <typename T>
void write(T x) {
    if (x < 0) putchar('-'), x = -x;
    if (x >= 10) write(x / 10);
    putchar('0' + x % 10);
}

const int N = 305;
char s[N];
ll n, m;
int g[N][2], nxt[N];

void KMP(void) {
    int j = nxt[1] = 0;
    for (int i = 2;i <= m; i++) {
        while (j && s[i] != s[j+1]) j = nxt[j];
        if (s[i] == s[j+1]) j++;
        nxt[i] = j;
    }
    for (int i = 0;i < m; i++) {
        int k = i, p = i;
        while (k && s[k+1] != '(') k = nxt[k];
        while (p && s[p+1] != ')') p = nxt[p];
        if (s[k+1] == '(') k++;
        if (s[p+1] == ')') p++;
        g[i][1] = k, g[i][0] = p;
    }
    g[m][0] = g[m][1] = m;
}

const int P = 1e9+7;
ll f[N][N][N];

inline void add(ll &x, ll y) {
    x += y; if (x >= P) x -= P;
}

int main() {
    read(n); int al = n << 1;
    scanf ("%s", s + 1);
    m = strlen(s + 1);
    KMP();
    f[0][0][0] = 1;
    for (int i = 0; i < al; i++) {
        for (int j = 0; j <= n; j++) {
            for (int k = 0; k <= m; k++) {
                ll t = f[i][j][k];
                if (j) add(f[i+1][j-1][g[k][0]], t);
                add(f[i+1][j+1][g[k][1]], t);
            }
        }
    }
    cout << f[al][0][m] << endl;
    return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!