Erase Subsequences
题目传送门:
思路:
看到题目最先想到的就是你可以枚举切割字符串的位置,使其分成两个串。然后接着一个最为朴素的n^3的dp就是,dp[ i ][ j ][ k ]
来表示字符串s匹配到第i位,t1字符串匹配到第 j 位,t2 字符串匹配到第k位时是否可行,可行则为1不行则为0。那么这样时间复杂度就来到了n^4方,即使数据很小,这样还是会T的。那么我们就要想办法削减一下dp的复杂度,一个容易想到的优化就是用dp[ i ][ j ]表示s匹配到第i位,t1字符串匹配到第 j 位时t2字符串所能匹配的最长的长度。那么这个问题就变得非常经典了。
AC Code
#include<bits/stdc++.h>
using namespace std;
const int N=500;
char s[N],t[N];
int dp[N][N];
int solve(string t1,string t2)
{
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=strlen(s+1);i++) //遍历s字符串
{
for(int j=0;j<t1.length();j++) //枚举t1匹配的长度
{
if(dp[i-1][j]>=0) dp[i][j]=max(dp[i][j],dp[i-1][j]);
if(s[i]==t1[j]&&dp[i-1][j-1]>=0)
dp[i][j]=max(dp[i-1][j-1],dp[i][j]);
if(dp[i-1][j]>=0)
{
dp[i][j]=max(dp[i-1][j],dp[i][j]);
if(s[i]==t2[dp[i-1][j]+1]&&dp[i-1][j]+1<t2.length())
{
dp[i][j]=max(dp[i][j],dp[i-1][j]+1);
}
}
}
}
if(dp[strlen(s+1)][t1.length()-1]==t2.length()-1) return 1;
/*for(int i=1;i<=strlen(s+1);i++)
{
if(dp[i][t1.length()-1]==t2.length()-1) return 1;
}*/
return 0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s+1); //下标从1开始
scanf("%s",t+1);
int flag=0;
for(int i=1;i<=strlen(t+1);i++) // 枚举分割的位置
{
string t1=" ",t2=" ";
for(int j=1;j<=i;j++) t1+=t[j];
for(int j=i+1;j<=strlen(t+1);j++) t2+=t[j];
if(solve(t1,t2))
{
flag=1;
printf("YES\n");
break;
}
}
if(flag==0) printf("NO\n");
}
//system("pause");
return 0;
}