括号匹配(二)--侥幸通过,用动态规划的思想

地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=15

原题:

括号匹配(二)

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 6
描述
给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
如:
[]是匹配的
([])[]是匹配的
((]是不匹配的
([)]是不匹配的
输入
第一行输入一个正整数N,表示测试数据组数(N<=10)
每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100
输出
对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行
样例输入
4
[]
([])[]
((]
([)]
样例输出
0
0
3
2

思路:用到 的思想,进行括号匹配。。除了能通过案例的测试外,还要通过这两个特例: (([))  和 ((])) 就基本可以了。 分享下自己的代码:
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Main main = new Main();
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		while (n-- > 0) {
			String str = sc.next();
			main.minBracket(str);
		}
	}

	public void minBracket(String str) {
		int length = str.length();
		int top1 = 0, top = length - 1, sum = 0;	//两个top来控制移动
		char[] chArr1 = new char[length];
		char[] chArr = str.toCharArray();
		while (top >= 0) {
			switch (chArr[top]) {
			case '(':
				if (top1 <= 0) {
					sum++;
					top--;
				} else if (chArr1[top1 - 1] != '(') {	//出栈匹配
					sum++;
					if(top>=top1)	//进行判断是哪个top进行移动,为了区分(([))和((]))这两个特例
					top--;
					else
						top1--;
				} else {
					top1--;
					top--;
				}
				break;
			case '[':
				if (top1 <= 0) {
					sum++;
					top--;
				} else if (chArr1[top1 - 1] != '[') {
					sum++;
					if(top>=top1)	//发现两个特例中比较长的那段,要先减--;
						top--;
						else
							top1--;
				} else {
					top1--;
					top--;
				}
				break;
			case ')':					//进栈
				chArr1[top1++] = '(';
				top--;
				break;
			case ']':
				chArr1[top1++] = '[';
				top--;
				break;

			}
		}
		System.out.println(sum+top1);	//要加上右边压进了栈后,左边在也没有可以匹配的情况
	}

}

网上有说是: 石子合并的思想:http://blog.sina.com.cn/s/blog_8e0ea6d50101qyky.html
在讨论区看到应该用 动态规划 的思想进行讨论求解。
35楼   loveyy 回复 2014-05-30 13:51:21
假定:
1. s(i)表示括号字符串中第i个字符;
2. d[i][j]表示使括号字符串s(i)s(i+1)...s(j)匹配最少需要添加的括号的数量(i<=j);
3. s(i)=s(j)表示s(i)与s(j)匹配。
讨论:
字符串s(i)s(i+1)...s(j)最优匹配有两种情况:
a. 最优匹配时s(j)需另外加字符与之匹配;
b. 最优匹配时s(j)与s(i)s(i+1)...s(j-1)中的某个字符匹配。

情况a有三种情况:
a1: 外加字符在s(i)左侧,则d[i][j]=d[i][j-1]+1;
a2: 外加字符在s(j)右侧,则d[i][j]=d[i][j-1]+1;
a3: 外加字符k在s(m)与s(m+1)之间(i=<m<=j),即s(i)...s(m)ks(m+1)...s(j),则d[i][j]=d[i][m]+d[m+1][j-1]+1.
由定义可知,d[i][j-1]<=d[i][m]+d[m+1][j-1],因此,为达到最优匹配的目的,对于情况a有:
d[i][j]=d[i][j-1]+1.

再来讨论情况b:
假设s(j)与s(i)s(i+1)...s(j-1)中的s(m)匹配,则d[i][j]=d[i][m-1]+d[m+1][j-1];需要注意的是,s(i)s(i+1)...s(j-1)中与s

(j)可以匹配的可能不止一个,应该对所有可以与s(j)匹配的s(m)都要进行讨论。
综上可知,对于情况b有:
d[i][j]=min{d[i][m-1]+d[m+1][j-1],i=<m<=j-1&&s(m)=s(j)}.

综合情况a和b可以知道:
d[i][j-1]+1;(没有与s[j]匹配的)
d[i][j]=
min{d[i][j-1]+1,min{d[i][m-1]+d[m+1][j-1],i=<m<=j-1&&s(m)=s(j)}}.(有与s[j]匹配的)

最后:
由d[i][j]的转移方程可以知道,d[i][j]的求解依赖于d[i][j-1]、d[i][m-1]、d[m+1][j-1],因此求解的方向应该是:d[1][2],d[2][3],d[1][3],d[3][4],d[2][4],d[1][4]...




  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值