牛客-删括号

题目描述

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

解题思路

看完题目我首先想的是暴力模拟,判断每一对“()”是否删除,但是这样写的话需要对每一对括号进行标记,时间复杂度会有2^50,超时所以不行。

既然如此那就换一种思路,我们可以用一个数组dp[i][j][k]来表示字符串s前i位与字符串t前j位的匹配情况(k=删除的 '(' 数-删除的')'数,即多删除的'('数),如果dp[s.len][t.len][0]=true,则表示s可以变成t,反之则不行,那我们就从dp[0][0][0]=1开始往后判断。

我们可以这么思考,如果s可以变成t,s’(由s去掉末尾的一小部分而来)可以变成t或t'(t'和s'类似),s''同理,则状态转移方程为

dp[ii][jj][kk]=(dp[i][j][k])&true;(ii,jj,kk为i,j,k变化而来,可能相同,可能加1)

即最终的dp[s.len][t.len][0]是由dp[i][j][k]变化而来,dp[i][j][k]同理

则我们需要找到dp[i][j][k]为true

当状态dp[i][j][k]=true的情况下,对于两个串的下一个字符,只有以下四种情况:

 我们分情况讨论:第一种情况,可以推出dp[i+1][j+1][k]=true或dp[i+1][j][k+1]=true;

对于第二种情况可以推出dp[i+1][j][k+1]=true;

对于第三种情况可以推出dp[i+1][j+1][k]=true或dp[i+1][j][k-1]=true;

对于第四种情况可以推出dp[i+1][j][k-1]=true;

对表达式进行归类,相同的放在一起,总结得出如果后一个字符相等且k=0,那么dp[i+1][j+1][0]=true,如果s的后一个字符是左括号,那么dp[i+1][j][k+1]=true,如果都不满足,并且k!=0,那么dp[i+1][j][k-1]=true。

思路都清晰了,那我们直接按照思路写代码就可以了。

题解代码

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
char s[110],t[110];
bool dp[110][110][60];

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    ///关闭输入输出流
    cin>>s+1>>t+1;
    int p=strlen(s+1);
    int q=strlen(t+1);
    dp[0][0][0]=1;
    for(int i=0;i<=p;i++){
        for(int j=0;j<=q;j++){
            for(int k=0;k<=p/2;k++){
                ///状态转移方程dp[ii][jj][kk]=(dp[i][j][k])&true;
                if(dp[i][j][k]){///找到dp[i][j][k]为true
                    if(!k&&s[i+1]==t[j+1])dp[i+1][j+1][k]=1;
                    if(s[i+1]=='(')dp[i+1][j][k+1]=1;
                    else if(k)dp[i+1][j][k-1]=1;
                    ///分情况讨论的总结,从i,j,k变为ii,jj,kk,分情况而定
                }
            }
        }
    }
    if(dp[p][q][0])cout<<"Possible\n";
    else cout<<"Impossible\n";
    return 0;
}

差不多就这样吧,我也暂时想不到什么了,如果看完之后有问题可以在下面评论或者直接私信我,我看到了就会回复的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值