UVA1626 括号序列 Brackets sequence(区间DP匹配括号,输出匹配方案)

整理的算法模板合集: ACM模板


UVA1626 括号序列 Brackets sequence
在这里插入图片描述

简单的区间DP,但是要输出方案,所以我们按照转移的方法再重新来一遍即可。

需要注意的是输入有可能是空串,所以需要用两次getline

输出时考虑四种情况:

  • i>j不是子串,return 0;
  • i == j子串长度为1说明是一个孤立点,补齐输出,return 1;
  • s = (s') 或 s = [s']那么返回的是f(i + 1, j - 1)
  • 其他情况,枚举断点
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>

using namespace std;
typedef long long ll;
const int N = 507, M = 5000007, INF = 0x3f3f3f3f;
const double eps = 1e-6;

int n, m, t;
int a[N];
int f[N][N];
int b[N];
string s;

bool match(char a, char b)
{
    if(a == '[' && b == ']')return true;
    if(a == '(' && b == ')')return true;
    return false;
}

//按照转移的方法完全的再倒推一遍
void print(int i, int j)
{
    if(i > j)return ;
    if(i == j){
        if(s[i] == '(' || s[i] == ')')printf("()");
        else printf("[]");
        return ;
    }
    int ans = f[i][j];
    if(match(s[i], s[j]) && ans == f[i + 1][j - 1]){
        printf("%c", s[i]);
        print(i + 1, j - 1);//往里缩
        printf("%c", s[j]);//包起来
        return ;
    }
    for(int k = i; k < j; ++ k){
        if(ans == f[i][k] + f[k + 1][j]){
            print(i, k);
            print(k + 1, j);
            return ;
        }
    }
}

int main()
{
    scanf("%d", &t);
    getchar();
    while(t -- ){
        memset(f, 0x3f, sizeof f);
        getline(cin, s);//注意因为可能有空串所以要输入两次
        getline(cin, s);
        n = s.length();
        if(n == 0){
            puts("");
            puts("");
            continue;
        }
        //f[i][j]表示s[i~j]至少要添加多少个括号
        for(int i = 1; i < n; ++ i){
            f[i][i] = 1;
            f[i][i - 1] = 0;
        }
        f[0][0] = 0;
        for(int i = n - 1; i >= 0; -- i){//左
            for(int j = i + 1; j < n; ++ j){//右
                //f[i][j] = INF;
                if(match(s[i], s[j]))//方案1,相同可内缩
                    f[i][j] = min(f[i][j], f[i + 1][j - 1]);
                for(int k = i; k < j; ++ k){//方案2,至少大于2,可以分开
                    f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j]);
                }
            }
        }
        print(0, n - 1);
        puts("");
        if(t)puts("");
    }
    return 0;
}

©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页