删括号(牛客)

链接:https://ac.nowcoder.com/acm/problem/21303
来源:牛客网

题目描述
给你一个合法的括号序列s1,每次你可以删除一个"()"
你可以删除0个或者多个"()"
求能否删成另一个括号序列s2
输入描述:

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

输出描述:

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

示例1
输入
复制

(())
()

输出
复制

Possible

示例2
输入
复制

()
()

输出
复制

Possible

示例3
输入
复制

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

输出
复制

Impossible

示例4
输入
复制

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

输出
复制

Possible

示例5
输入
复制

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

输出
复制

Impossible

备注:

子任务1: |s| <= 10
子任务2: |s| <= 20
子任务3: 无限制
我们先谈谈简单的思路,最内层的循环是为了找到一个e使s能够删除e个‘( ’ 能与t匹配【e = ‘(’ - ‘)’ 的数目】,所谓的匹配就是s和t相差n个();知道了这个以后我们就要对s和t进行动态维护;
我们先假定t 取前i项不动,对s进行动态处理,每次都增加s的一项,我们要判断s的前j项和t的前i项能否通过处理e值来匹配,如果可以我们就称之为可能达到目标的状态,我们要用动态方程1
if(s[q+1]==’(’ ) dp[q+1][w][e+1]=true;
else if(k) dp[q+1][w][e-1]=true;
随后我们要变动t,每次增一下,当然这种增加也不是随便能增的,我们必须在上面所说的状态为true时判断,其中是否有一种情况能满足e=0,且s[q+1]=t[w+1]?为什么这样做就是对的呢,我们回到我们刚刚开头的地方,当dp[0][0][0]=true时对于s[q+1]和t[w+1]而言他们满足我们上述所说的方程,我们每动一次t就是不断扩大我们的子问题,保证在t增加的时候我们当前获得的s,t子串能够能够通过删除n个()来匹配;这里我们就明白了,该题题意所要求问题的解答的一般情况是s删n个()能与t匹配,想想是不是。
所以我们通过这三个判断式能获得所有的一般解,当然满足s和t是括号序列的特殊情况就包含在内了;
以下是代码提供参考
//注意dp[q][w][e]=true是指s前q项与t前w项能通过删除e个多余 '( '实现匹配;所以我们输入时一定要注意 从数组第1项开始输入,切记不要从0项开始输入,因为s[0]是s的第一项,而dp[0][][]表示s的前0项…;

#include<bits/stdc++.h>
using namespace std;
int main(){
    char s[105],t[105];
    scanf("%s%s",s+1,t+1);
    int len1=strlen(s+1);
    int len2=strlen(t+1);
    bool dp[105][105][55];
    memset(dp,0,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++){
                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;
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值