codeforces 1272F dp+记录路径

题意

给出两个括号序列 \(S\)\(T\),让你构造一个最短的合法括号序列使 \(S\)\(T\) 是它的子序列。

分析

\(dp[i][j][k]\) 为这个最短的合法括号序列的前缀包含 \(S\) 的前 \(i\) 个字符,T的前 \(j\) 个字符且左括号的数量大于右括号的数量为 \(k\)时的长度。

  • 如果我们要添加一个左括号

    \(dp[nexi][nexj][k+1]=min(dp[i][j][k]+1,dp[nexi][nexj][k+1])\)

    \(nexi\) 为添加一个左括号后能匹配到的下一个 \(i\)\(nexj\) 为添加一个左括号能匹配到的下一个 \(j\)

  • 如果我们要添加一个右括号

    \(dp[nexi][nexj][k-1]=min(dp[i][j][k]+1,dp[nexi][nexj][k-1])\)

    \(nexi\) 为添加一个右括号后能匹配到的下一个 \(i\)\(nexj\) 为添加一个右括号能匹配到的下一个 \(j\)

\(dp\) 过程中用一个数组记录下转移的前驱就可以倒推还原这个括号序列。

Code

#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
#define pb push_back
#define ll long long
using namespace std;
const int inf=1e9;
const int mod=1e9+7;
const int maxn=2e2+10;
char s[maxn],t[maxn];
int n,m;
int dp[maxn][maxn][2*maxn];
struct ppo{
    int x,y,k;
    char c;
}pre[maxn][maxn][2*maxn];
int main(){
    //ios::sync_with_stdio(false);
    //freopen("in","r",stdin);
    scanf("%s%s",s,t);
    n=strlen(s);m=strlen(t);
    for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) for(int k=0;k<2*maxn;k++) dp[i][j][k]=inf;
    dp[0][0][0]=0;
    for(int i=0;i<=n;i++){
        for(int j=0;j<=m;j++){
            for(int k=0;k<2*maxn;k++){
                if(dp[i][j][k]==inf) continue;
                int x=i+(i<n&&s[i]=='(');
                int y=j+(j<m&&t[j]=='(');
                if(k+1<2*maxn&&dp[i][j][k]+1<dp[x][y][k+1]){
                    dp[x][y][k+1]=dp[i][j][k]+1;
                    pre[x][y][k+1]=ppo{i,j,k,'('};
                }
                x=i+(i<n&&s[i]==')');
                y=j+(j<m&&t[j]==')');
                if(k>0&&dp[i][j][k]+1<dp[x][y][k-1]){
                    dp[x][y][k-1]=dp[i][j][k]+1;
                    pre[x][y][k-1]=ppo{i,j,k,')'};
                }
            }
        }
    }
    string str;
    int x=n,y=m,k=0,p=0;
    for(int i=0;i<2*maxn;i++){
        if(dp[n][m][p]+p>dp[n][m][i]+i) p=i;
    }
    for(int i=0;i<p;i++) str.pb(')');
    k=p;
    for(int i=0;i<dp[n][m][p];i++){
        ppo p=pre[x][y][k];
        str.pb(p.c);
        x=p.x;y=p.y;k=p.k;
    }
    reverse(str.begin(), str.end());
    cout<<str<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xyq0220/p/12061335.html
今日推荐