zoukankan      html  css  js  c++  java
  • CodeForces

    题目链接

    题目大意

      给你一个字符串s,问长度为2n并且s为其子串的字符串有多少个。

    解题思路

      一开始我想了几种状态方案,都有重复的情况,后来看了题解才知道还能这样做。我们设dp数组为dp[i][j][k],分别表示在长度为2n的字符串的第i位,括号序列的匹配度为j(遇到左括号+1,遇到右括号-1),并且这个字符串的后缀(其实不是严格的后缀,也可以包含首位)与s的前缀匹配了k个字符时的方案数。这样设计状态之后,我们在添加括号的过程中,不仅j会改变,k的值也可以改变,我们可以预处理出来在匹配了k个字符之后再在这个字符串末尾添加左括号或者右括号时它的后缀与s的前缀的最大匹配位数,设这个函数为f(k, 左括号 or 右括号),那么状态转移方程就可以写成:
      dp[i+1][j+1][f[k][0]] += dp[i][j][k];
      dp[i+1][j-1][f[k][1]] += dp[i][j][k];
      注意如果之前的后缀匹配的长度和s的长度相等了,即使再往后添加括号,也不用再改变匹配的长度了。
      这个方案很好的避免了同一方案被重复计算的问题,比如字符串s为"(("对于方案"(((())))"来说,如果会重复计算的话,可能会被记成4种方案,但是如果用上面的方法,这一方案只能是两个字符串前两个字符匹配的情况,就不会再被重复算进去了。

    代码

    #include<bits/stdc++.h>
    #define endl '
    '
    #define x first
    #define y second
    #define clr(arr,a) memset(arr, a, sizeof(arr))
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll, ll> P;
    typedef pair<int, int> Pll;
    const double pi = acos(-1.0);
    const double eps = 1e-8;
    const int MOD = 1e9+7;
    const int INF = 0x3f3f3f3f;
    const int maxn = 2e2+10;
    const int maxm = 2e6+10;
    char s[maxn];
    int nxt[maxn], f[maxn][2];
    ll dp[maxn][maxn][maxn];
    void kmp() {
        int len = strlen(s+1);
        int i = 1, j = 0; nxt[1] = 0;
        while(i<=len) {
            while(j && s[i]!=s[j]) j = nxt[j];
            //cout << s[i] << ' ' << s[j+1] << endl;
            nxt[++i] = ++j;
        }
        for (int i = 0; i<len; ++i) {
            int p = i+1;
            int q = i+1;
            while(p && s[p]!='(') p = nxt[p];
            f[i][0] = p;
            while(q && s[q]!=')') q = nxt[q];
            f[i][1] = q;
        }
        f[len][0] = f[len][1] = len;
    }
    int main() {
        int n; cin >> n >> s+1;
        kmp();
        n <<= 1;
        dp[0][0][0] = 1;
        int len = strlen(s+1);
        for (int i = 0; i<n; ++i)
            for (int j = 0; j<=n; ++j)
                for (int k = 0; k<=len; ++k) {
                    if (j+1<=n) dp[i+1][j+1][f[k][0]] = (dp[i+1][j+1][f[k][0]]+dp[i][j][k])%MOD;
                    if (j) dp[i+1][j-1][f[k][1]] = (dp[i+1][j-1][f[k][1]]+dp[i][j][k])%MOD;
                }
        cout << dp[n][0][len] << endl;
        return 0;
    }
    
  • 相关阅读:
    python 中 time 模块 格式化 format
    python 以标准输出(sys.stdout)为例,看python的标准输入、标准错误输出
    Quick-lua3.3之listview
    健身计划表
    quick-cocos2d-x 实现在lua里面完成android支付宝的接入
    lua table 排序--满足多条件排序
    lua 操作中文字符串之截取和长度竖排显示
    ClippingNode实现新手引导高亮裁切
    quick cocos2dx lua 内存释放
    cocos2d-x的lua脚本加载CocostudioUI两种方式
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/14659685.html
Copyright © 2011-2022 走看看