• Codeforces Round #501 (Div. 3)F. Bracket Substring+kmp+dp


    题目连接:F. Bracket Substring

    题意:输入一个数字n,和只有左右括号的s串,问有多少个长度为2*n完美串有s作为连续字串

    题解:dp+kmp的nxt数组。dp[i][j][k]表示那个2*n的串匹配到i这个位置有j个位置匹配,还有k个不匹配左括号的方案数

    状态转移时,要借助nxt数组处理出来的f[]数组,f[i]表示在第i个位置不匹配然后它能与原串开头匹配的长度,细节处看代码吧。最后答案就是dp[2*n][len][0]

    #include<bits/stdc++.h>
    #include<set>
    #include<cstdio>
    #include<iomanip>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #define pb push_back
    #define ll long long
    #define fi first
    #define se second
    #define PI 3.14159265
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define eps 1e-7
    #define pii pair<int,int>
    typedef unsigned long long ull;
    const int inf=1e9+1;
    const int mod=1e9+7;
    const int maxn=2e5+10;
    using namespace std;
    int n,nxt[250],f[250],dp[205][205][250];
    char s[maxn];
    void getnxt()
    {
        int j, k;
        j = 0; k = -1; nxt[0] = -1;
        int tlen=strlen(s);
        while(j < tlen)
            if(k == -1 || s[j] == s[k])
                nxt[++j] = ++k;
            else
                k = nxt[k];
        f[0]=0;
        for(int i=1;i<tlen;i++)
        {
            int j=nxt[i];
            while(j>=0&&s[j]==s[i])j=nxt[j];
            if(j<0)f[i]=0;
            else if(j>=0&&s[j]!=s[i])f[i]=j+1;
            else f[i]=0;
        }
    }
    void add(int &x,int y)
    {
        x+=y;
        if(x>=mod)x-=mod;
        if(x<0)x+=mod;
    }
    int main()
    {
        scanf("%d %s",&n,s);
        int len=strlen(s);
        dp[0][0][0]=1;
        getnxt();
        for(int i=0;i<2*n;i++)
        {
            for(int j=0;j<len;j++)
            {
                for(int k=0;k<=n;k++)
                {
                    if(s[j]=='(')
                    {
                        add(dp[i+1][j+1][k+1],dp[i][j][k]);
                    }
                    else add(dp[i+1][f[j]][k+1],dp[i][j][k]);
                    if(k)
                    {
                        if(s[j]==')')add(dp[i+1][j+1][k-1],dp[i][j][k]);
                        else  add(dp[i+1][f[j]][k-1],dp[i][j][k]);
                    }
                }
            }
            for(int k=0;k<=n;k++)
            {
                add(dp[i+1][len][k+1],dp[i][len][k]);
                if(k)add(dp[i+1][len][k-1],dp[i][len][k]);
            }
        }
        printf("%d
    ",dp[2*n][len][0]);
        return 0;
    }
  • 相关阅读:
    ORA01940: cannot drop a user that is currently connected
    struts+swfupload实现批量图片上传(下篇)
    iPhone开发入门教程
    从零开始学习OpenGL ES集合
    iPhone入门学习——半翻页动画效果例子
    《Android学习指南》目录
    基于OpenGL ES 的图片翻转例子,包含双面贴图3D变换
    Android核心分析
    ios开发之分享一个特效 Cube
    仿Drinkspiration App的menu
  • 原文地址:https://www.cnblogs.com/lhclqslove/p/9413563.html
Copyright © 2020-2023  润新知