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\n",dp[2*n][len][0]);
    return 0;
}

 

posted @ 2018-08-03 13:05  lhclqslove  阅读(124)  评论(0编辑  收藏  举报