地址: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]...
-
第一行输入一个正整数N,表示测试数据组数(N<=10)