原题链接:登录—专业IT笔试面试备考平台_牛客网
解题思路:本题可以利用动态规划来解题。首先题目内删除的括号对,必须是紧邻的,即括号对之间删除时不能间隔任何字符。也就是说,如果决定删除一个中间有字符串的括号对,那么括号对内的所有括号都必须被删除后,外层的括号对才能删除。
也就是说,一旦决定开始删除左括号,则必须在遇到右括号时一起消除,直到之前的所有被删除的左括号对应上右括号,才能不选择删除。如果在删除左括号但没碰到右括号,而是碰到了另一个左括号,则后者也必须被删除,因为删除的括号对间不能有字符。此时就需要多找一个右括号了。
那么在没有未匹配到右括号的已经被删除左括号(在下文简称剩余删除左括号数)时,才可以选择保留这个字符。当这个字符和t字符串的下一个字符匹配时,s字符串的位置和t字符串的待匹配字符位置才可以一起向后推移一位。
当s字符串与t字符串的匹配位置都达到末尾,且没剩余删除左括号数为0的情况是可以达到的,才输出可能。
AC代码:
#include<bits/stdc++.h>
using namespace std;
string s,t;//题目原意
long long ls,lt;//s字符串的长度与t字符串的长度
bool dp[150][150][150];//dp用数组,记录当前是否匹配
//dp数组的第一维为s字符串位置,第二维是t字符串位置,第三维是当前已经消除了几个左括号但是还没有匹配到右括号
int main(){
dp[0][0][0]=1;//两个字符串都没开始匹配时,即空字符串,必然匹配
cin>>s>>t;
ls=s.length();
lt=t.length();
s=' '+s;
t=' '+t;
for(int i=0;i<=ls;i++){
for(int j=0;j<=lt;j++){
for(int k=0;k<=ls;k++){
if(dp[i][j][k]){//这种情况本身时可以达到的,才可以从这种情况推下一个情况
if(k==0&&s[i+1]==t[j+1]) dp[i+1][j+1][0]=1;//如果此时匹配,且不存在只消除左括号还没消除对应右括号时才会继承
//因为删除的括号一定为紧邻的,如果第三维不为0就开始匹配可能导致删除的左右括号间是有东西的
//除非对应的左右括号间的括号对都在之前删除了才能删除
if(s[i+1]=='(') dp[i+1][j][k+1]=1;//如果删除该左括号,则s字符串处理后的字符串,与t字符串已经比对的字符串依然匹配,因为这个左括号视作删除了
else if(k) dp[i+1][j][k-1]=1;//如果此时k不为0,即有没有匹配上的左括号,以及此时为右括号,所以可以对应删除
}
}
}
}
if(dp[ls][lt][0]) cout<<"Possible";//只有在所有删除的括号都合法的成对删除,k才为0。而s字符串与t字符串也已经匹配完相同,答案才为可能。
else cout<<"Impossible";
return 0;
}