题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5707
题意:给你一个字符串a,一个字符串b,一个字符串c,问你能否把c分解成两个子序列分别等于a和b。
思路:可以用BFS搜索拆字符串c,也可以用DP来判断a和b能否凑出c。
BFS代码:
#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
char a[2010],b[2010],c[2010];
int vis[2010][2010];
struct node
{
int a,b,c;
node (int aa,int bb,int cc):a(aa),b(bb),c(cc){}
};
int main()
{
int la,lb,lc,ta,tb,i,ans;
while(scanf("%s%s%s",a+1,b+1,c+1)!=EOF)
{
la=strlen(a+1);
lb=strlen(b+1);
lc=strlen(c+1);
if(la+lb!=lc)
{
printf("No\n");
continue;
}
//printf("%d\n",lc);
queue<node>q;
while(!q.empty())
q.pop();
q.push(node(0,0,1));
memset(vis,0,sizeof(vis));
vis[0][0]=1;
ans=0;
while(!q.empty())
{
node t=q.front();
//printf("%d %d %d\n",t.a,t.b,t.c);
q.pop();
if(vis[la][lb])
{
ans=1;
break;
}
if(t.a+1<=la&&a[t.a+1]==c[t.c]&&vis[t.a][t.b]==1&&vis[t.a+1][t.b]==0)
{
q.push(node(t.a+1,t.b,t.c+1));
vis[t.a+1][t.b]=1;
}
if(t.b+1<=lb&&b[t.b+1]==c[t.c]&&vis[t.a][t.b]==1&&vis[t.a][t.b+1]==0)
{
q.push(node(t.a,t.b+1,t.c+1));
vis[t.a][t.b+1]=1;
}
}
if(ans==0)
printf("No\n");
else
printf("Yes\n");
}
return 0;
}
DP代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 2010
int dp[N][N];
char a[N],b[N],c[N];
int main()
{
int i,j,k1,k2,k3,flag;
while(scanf("%s%s%s",a+1,b+1,c+1)!=EOF)
{
k1=strlen(a+1);
k2=strlen(b+1);
k3=strlen(c+1);
memset(dp,0,sizeof(dp));
if(k1+k2!=k3)
{
printf("No\n");
continue;
}
for(i=1;i<=k3;i++)
{
if(i<=k1&&a[i]==c[i])
dp[i][0]=dp[i-1][0]+1;
if(i<=k2&&b[i]==c[i])
dp[0][i]=dp[0][i-1]+1;
//a[j]结尾
for(j=1;j<=min(i,k1);j++)
{
if(a[j]==c[i])
dp[j][i-j]=max(dp[j][i-j],dp[j-1][i-j]+1);
}
//b[j]结尾
for(j=1;j<=min(i,k2);j++)
{
if(b[j]==c[i])
dp[i-j][j]=max(dp[i-j][j],dp[i-j][j-1]+1);
}
}
flag=0;
/*for(i=0;i<=k1;i++)
{
for(j=0;j<=k2;j++)
printf("%d ",dp[i][j]);
printf("\n");
}*/
if(dp[k1][k2]==k3)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}