HDU 5707-Combine String-动态规划

Given three strings a, b and c, your mission is to check whether c is the combine string of a and b.
A string c is said to be the combine string of a and b if and only if c can be broken into two subsequences, when you read them as a string, one equals to a, and the other equals to b.
For example, “adebcf” is a combine string of “abc” and “def”.

Input

Input file contains several test cases (no more than 20). Process to the end of file.
Each test case contains three strings a, b and c (the length of each string is between 1 and 2000).

Output

For each test case, print “Yes”, if c is a combine string of a and b, otherwise print “No”.

Sample Input

abc
def
adebcf
abc
def
abecdf

Sample Output

Yes
No

题目大意:

给定三个字符串a,b,c。问c是否能恰好拆分成两个子序列,其中一个子序列等于a,另外一个子序列等于b。

核心思想:

动态规划。
如果a的前i个字符和b的前j个字符能结合成(子序列式结合,不是单纯的拼接)c的前i+j个字符,则dp[i][j]=1,否则,dp[i][j]=0。
状态转移方程:
a的第i个字符等于c的第i+j个字符,或者b的第j个字符等于c的第i+j个字符
dp[i][j]=dp[i-1][j]&&a[i]==c[i+j]||dp[i][j-1]&&b[j]==c[i+j]
另外,模拟会有bug的,例如:
ab
ac
acab
正确答案是Yes,模拟一般会No。

代码如下:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=2020;
char a[N],b[N],c[N];
bool dp[N][N];
int main()
{
	while(scanf("%s%s%s",a,b,c)!=EOF)
	{
		int la=strlen(a);
		int lb=strlen(b);
		int lc=strlen(c);
		if(la+lb!=lc)
		{
			printf("No\n");
			continue;
		}
		//将字符都后移一位,方便初始化 
		for(int i=la;i>0;i--)
			a[i]=a[i-1];
		for(int i=lb;i>0;i--)
			b[i]=b[i-1];
		for(int i=lc;i>0;i--)
			c[i]=c[i-1];
		//初始化
		dp[0][0]=1;
		for(int i=1;i<=la;i++)
			dp[i][0]=dp[i-1][0]&&a[i]==c[i];
		for(int i=1;i<=lb;i++)
			dp[0][i]=dp[0][i-1]&&b[i]==c[i];
		//状态转移 
		for(int i=1;i<=la;i++)
			for(int j=1;j<=lb;j++)
				dp[i][j]=dp[i][j-1]&&b[j]==c[i+j]||dp[i-1][j]&&a[i]==c[i+j];
		//输出 
		if(dp[la][lb])
			printf("Yes\n");
		else
			printf("No\n");
	}
	return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值