括号匹配(二)

 

题目:http://acm.nyist.net/JudgeOnline/problem.php?pid=15

 

/*
问题:


给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
如:
[]是匹配的,所需括号个数为 0.
([])[]是匹配的, 所需括号个数为 0.
((]是不匹配的, 所需最少括号个数为 3.
([)]是不匹配的,所需最少括号个数为 2.




分析:

此题来自:http://blog.csdn.net/coolanfei/article/details/7475542, 作者同时给出了正确答案。但是,感觉答案还不是特别的详细,也不是特别容易懂。所以,在此写下自己的分析思路。

1. 我们用 mb[i][j] 表示从位置 i  到字符位置 j 所需的最少括号数。假定字符串是 “[ ( )”, 那么 mb[0][0] = mb[1][1]  = mb[2][2] = 1。

2. 如果我们要算mb[i][j+1], 那么,最坏的情况是使得没有被匹配的括号数增加了,即 mb[i][j+1] 最多为 min( mb[i][j] + 1, mb[i+1][j+1] + 1). 但是,这可能不是我们想要的答案,因为在刚才的例子里,即:假定字符串是 “[ ( )”, 那么 mb[0][1] = mb[0][0] + 1= 2, 但是 mb[1][2] 却不等于 mb[1][1] + 1.

3. 那么,什么情况下mb[i][j+1] = mb[i][j] + 1?只有当 字符串里从i 到 j 没有任何字符与第 j + 1 个字符匹配的时候。但是,如果存在和第 j + 1 个字符匹配的情况,问题就不一样了。

4. 假设在i 到 j 之间存在一个字符(比如在位置 k)与第 j + 1 个字符匹配,那么我们相当于把原来的字符串分成了两个部分mb[i][k-1] 和 mb[k+1][j], 因为第k 个 和 j + 1 个字符已经匹配掉了。而且,我们不会再考虑 i 到 k - 1 的字符会和 k + 1 到 j 之间的字符匹配的情况,因为我们已经把这两个部分完全分开了(很重要的一点,这也是我当时思考很久的地方)。话句话说 mb[i][j+1] = min(min( mb[i][j] + 1, mb[i+1][j+1] + 1),  mb[i][k-1] + mb[k+1][j]).


有了这样的分析,我们可以利用动态规划的思路来解决这样的问题。代码如下:

思路来自:http://blog.csdn.net/beiyeqingteng/article/details/7695274
自己又写了一遍。

*/

#include <iostream>
#include <string.h>
#include <string>

using namespace std;

const int dpSize=105;
int dp[dpSize][dpSize];

bool isMatch(const char& s1,const char &s2)
{
	if ( (s1=='(' && s2==')') || (s1=='[' && s2==']') ){
		return true;
	}
	return false;
}


void sulotion(const string &str)
{
	memset(dp,0,sizeof(dp));
	for ( int i=0 ; i<dpSize ; ++i ){
		dp[i][i]=1;
	}
	const int strLen=str.length();
	for ( int i=1 ; i<strLen ; ++i ){
		for ( int j=0 ; j<i ; ++j ){
			int min=dp[j][i-1]+1;
			for ( int k=j ; k<i ; ++k ){
				if ( isMatch(str[k],str[i]) ){
					//当dp的第一维大于第二维时候为0
					min=(dp[j][k-1]+dp[k+1][i-1])<min ? (dp[j][k-1]+dp[k+1][i-1]):min ;
				}
			}
			dp[j][i]=min;
		}
	}

	cout<<dp[0][strLen-1]<<endl;
}

int main()
{
	int t;
	cin>>t;
	string str;
	while (t--){
		cin>>str;
		sulotion(str);
	}
	return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值