题目描述
给你一个合法的括号序列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;
}