牛客NC21303删括号

该问题是一个关于字符串处理的编程挑战,通过动态规划方法解决。给定两个合法的括号序列S1和S2,判断是否能通过从S1中删除一些或不删除括号,使其变成S2。输入是两个字符串,输出是可能或不可能。示例展示了不同情况下的正确结果。解决方案涉及状态转移矩阵和字符串匹配策略。
摘要由CSDN通过智能技术生成

题目链接
删括号 (nowcoder.com)

题目描述

给你一个合法的括号序列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:无限制

思路

DP解法:创建bool型的dp[ i ][ j ]表示字符串s的前i位能否通过删括号或者不删来得到t的前j位

AC代码

#include<bits/stdc++.h>
using namespace std;
string s,t;//存储字符串s和t
int lens,lent;//字符串s和t的长度
bool dp[101][101];//bool型的dp[i][j]表示字符串s的前i位能否通过删括号或者不删来得到t的前j位
int main(){
    //输入数据
    cin>>s>>t;//输入字符串s和t
    lens=s.size();//字符串s的长度
    lent=t.size();//字符串t的长度
    //dp的初始化
    for(int i=0;i<=min(lens,lent);i++)dp[i][0]=1;//dp[i][0]=1可理解为s的前i位可以通过删括号或者不删来得到t的前0位,当然这里的min(lens,lent)也可替作max(lens,lent)
    //推导(状态转移)
    for(int i=1;i<=lens;i++){//s当前处理到第i位
        for(int j=1;j<=lent;j++){//t当前处理到第j位
            if(s[i-1]==t[j-1])dp[i][j]=dp[i-1][j-1];//如果这两位相等就继承共同少一位dp[i-1][j-1]的状态
            if(s[i-1]==')'){//以')'为标准往前删除括号(而且题目说s必合法,无需做过多担心)
                int k=i-1;//用k来往前遍历
                int cnt=1;//cnt来记录‘)’比'('多多少
                while(cnt>0) {//还未到删除条件
                    if (s[k - 1] == ')') cnt += 1;//遇‘)’加1
                    else cnt -= 1;//遇'('减1
                    k -= 1;//往前遍历
                }//这里有小伙伴会问:为什么只删了就近的括号?解释:因为前边遍历的时候已经把之前的可以成括号的情况都包含进去了
                dp[i][j]|=dp[k][j];//继承删完括号后长为k的s对于自己本身前j位的状态
                //PS;|=的使用很关键 因为有种情况:第16行代码dp[i][j]继承dp[i-1][j-1]为真但是删完dp[k][j]为家的话,用=就会替换,导致结果出错
            }
        }
    }
    //结果的判断
    if(dp[lens][lent]) cout<<"Possible"<<endl;//为真输出"Possible"
    else cout<<"Impossible"<<endl;//为假输出“Impossible”
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Felix_wjl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值