21303 删括号

题目描述
给你一个合法的括号序列s和t,能否在s中删除若干对括号(或者不删除括号),使之变成序列t。

题目描述

第一行输入一个字符串s (2 ≤ |s| ≤ 100)
第二行输入一个字符串 t (2 ≤ |t| ≤ 100 )

输出描述

如果可以输出"Possible",否则输出"Impossible"

示例一
输入

(())
()

输出

Possible

示例二
输入

(()()())
((()))

输出

Impossible

示例三
输入

((())((())())())
(()(())())

输出

Possible

  这个题目看起来毫无思路,I think so,开始认为从以t能否增加括号形成至t,其实这种思路是没有问题。。。
  正解为定义一个dp[i][j][k],表示序列s的前i个且删除掉k个左括号’('的情况下,可以与序列t的前j个括号进行匹配,每删除一个括号,对应的k值因减1,最终判断条件为dp[len1][len2][0]是否为true
在dp[i][j][k] = true(可匹配)前提下,对s,t的下一个字符进行匹配:
1. s的左括号与t的左括号进行匹配
dp[i + 1][j + 1][k] = true或dp[i + 1][j][k + 1] = true
2. s的左括号与t的右括号进行匹配
dp[i + 1][j][k + 1] = true
3. s的右括号与t的右括号进行匹配
dp[i + 1][j + 1][k] = true或dp[i + 1][j][k - 1] = true
4. s的右括号与t的左括号进行匹配
dp[i + 1][j][k - 1] = true
1, 3两种情况可以进行综合,即为在k = 0时最后一个字符相等(’('或‘)’),dp[i + 1][j + 1][k] = true,如果s下一个字符为左括号,dp[i + 1][j][k + 1] = true,否则在k不为0时dp[i + 1][j][k - 1] = true

不太好理解,大家仔细斟酌。。。。。。

#include <iostream>
#include <cstring>
using namespace std;

//dp[i][j][k]表示序列 s 在前 i 个并且删除 k 个左括号'('时可以与序列 t 
//的前 j 个进行匹配, 匹配成功则为 true, 否则为 false 

int main()
{
	string s, t;
	cin >> s >> t;
	int len1 = s.length();
	int len2 = t.length();
	bool dp[102][102][102];
	memset(dp, false, sizeof(dp)); 
	dp[0][0][0] = true;
	for(int q = 0; q < len1; ++q)
	{
		for(int w = 0; w < len2; ++w)
		{
			for(int e = 0; e < len1 / 2; ++e)//只走了len1 / 2,  
			{
				if(dp[q][w][e])
				{
					if(e == 0 && s[q + 1] == t[w + 1]) dp[q + 1][w + 1][0] = true;
					
					if(s[q + 1] == '(') dp[q + 1][w][e + 1] = true;
					else if(e) dp[q + 1][w][e - 1] = true; 
				}
			}
		}	
	}
	if(dp[len1][len2][0]) cout << "Possible" << endl;
	else cout << "Impossible" << endl;
	return 0; 
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值