动态规划 括号匹配(二)问题

 

   括号匹配(二)

时间限制:1000 ms  |  内存限制:65535 KB

难度:6

描述

给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。

如:

[]是匹配的

([])[]是匹配的

((]是不匹配的

([)]是不匹配的

输入

第一行输入一个正整数N,表示测试数据组数(N<=10)

每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100

输出

对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行

样例输入

4

[]

([])[]

((]

([)]

样例输出

0

0

3

2

来源

《算法艺术与信息学竞赛》

上传者

张云聪

     AC 0.32

 

一开始用栈来做,判断是否匹配,不匹配则计数+1,计算出不匹配个数。这种算法处理不了很多数据。

然后又改成两端向内依次寻找匹配,匹配则删去然后再寻找这个匹配里面的括号。一部分匹配完后,继续在没有匹配的数据中寻找,直到所有数据都被处理。这个算法比上面的好一点,但是不能处理()()或([)(])这样的特殊数据。

最后查到了用动态规划来做,然后又设计了第三种算法,成功AC。

 

动态规划思路:

把问题分为几个阶段,分别求解,将每一次运算的结果保存在一个二维数组中,以后的求解过程可以使用之前的运算结果。

 

本题思路:

可以把字符串分解,有以下这几种情况:

1.S="("等,此时dp=1.

2.S="(S')",S需要的最小括号数=S'

3.S="S'1+S'2",S需要的最小括号数=S'1的+S'2的

 

 

1.首先,建立一个二位数组dp[][]来存储结果,dp[i][j]表示从S[i]到S[j]的最少添加括号个数。

2.那么首先可以把dp[i][j](i==j)的值存为1,因为一个字符必定需要添加一个括号。其他值先赋值为0。(阶段0)

3.然后,进行循环遍历,每阶段考虑k个长度的区间(k从1到总长),每次考虑i,j内的区间(i从0开始依次考虑),如果S[i]==S[j],说明他们是匹配的,dp[i][j]=dp[i+1][j-1](括号里面部分需要添加的最小括号数)

4.此外,该题还有分割情况(比如"[[[]]][[[]]]"需要分成两部分考虑),应依次考虑所有分割情况,如果进行了某种分割后,最多需要添加括号更少,就采用更小的值,所以有for(int k = i;k

5.全部处理完后,dp[0][length-1]即为S[0]S[length]也就是整个字符串需要添加的最小括号数。

又该题可以看出,动态规划实际遍历了所有可能结果,其中用二维数组保存一些结果,加快了运算速度。

 

手动演算"[((](]"的结果:

动态规划 括号匹配(二)问题_第1张图片

源码

#define R 105
#include
#include
int length(char s[]){
    int i=0;
    while(s[i++]!='\0');
    return i-1;
}
bool match(char a,char b){
    if(a=='('&&b==')')return 1;
    if(a=='['&&b==']')return 1;
    return 0;
}
int min(int a,int b){
    if(a

另外符上失败的两种算法(注意这两种是错的):

#include
int length(char s[]){
    int i=0;
    while(s[i++]!='\0');
    return i-1;
}
int main(){
    int n,l,i,x,number;
    char all[105],S[105];
    scanf("%d",&n);
    while(n--){
        number = 0;
        x = 0;
        scanf("%s",all);
        l = length(all);
        for(i=0;i
#include
int length(char s[]){
    int i=0;
    while(s[i++]!='\0');
    return i-1;
}
char match(char a){
    if(a == '(')
        return ')';
    else if(a == '[')
        return ']';
    else
        return '\0';
}
int main(){
    int n,l;
    int a,number;
    int i,j;
    char all[105];
    scanf("%d",&n);
    while(n--){
        number = 0;
        scanf("%s",all);
        l = length(all);
        a = l - 1;
        for(i=0;i=i;j--){
                    if(all[j]==match(all[i])){
                        //printf("match %d == %d\n",i,j);
                        all[j]='\0';
                        a=j-1;
                        break;
                    }
                    else if(i==j){
                        number++;
                        break;
                    }
                }
            }
            else if(i>=a){
                while(all[++i]=='\0');
                i--;
                a = i;
                while(all[++a]!='\0'&&a

 问题地址传送门

资料传送门

你可能感兴趣的:(数据结构和算法,acm,动态规划)