E - Combine String (hdu 5707)

https://vjudge.net/contest/303039#problem/E

大概题意:

给你字符串a、b、c,那么c是否可能由a、b组成(a,b可以打散,顺序组成c)

dp思想:

原沙雕思想:dp数组为string类型的,根据a和b一步步递推出所有能组合的字符串,当然内存超限了,像bfs想法

dp[[i][j]表示a数组取i个,b数组取j个能组成的字符串

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#define rep1(i,s,e,c) for(int i=s;i<e;i=i+c)
#define rep2(i,s,e,c) for(int i=s;i<=e;i=i+c)
#define rep3(i,e,s,c) for(int i=e;i>=s;i=i-c)
using namespace std;
typedef long long ll;
const int MAX=2e5+1;
const int MOD=1e9+7;
string str[2005][2005];
int main()
{
    string a,b,c;
    while(cin>>a>>b>>c){
    	str[0][0]="";
    	for(int i=0;i<=a.length();i++){
    		for(int j=0;j<=b.length();j++){
    			if(i+1<=a.length()&&str[i+1][j]!=c.substr(0,i+j+1)){
    				str[i+1][j]=str[i][j]+a[i];
				}
				if(j+1<=b.length()&&str[i][j+1]!=c.substr(0,i+j+1)){
					str[i][j+1]=str[i][j]+b[j];
				}
			}
		}
		if(str[a.length()][b.length()]==c){
			cout<<"Yes\n";
		}
		else cout<<"No\n";
	}
    return 0;
}

新写法:

dp[i][j]表示a数组前i个字符和b数组前j个字符和c前i+j个字符是否匹配,0则不匹配,1则匹配

dp[i][j]=dp[i-1][j] | dp[i][j-1](我是反过来递推的)

注意这种dp一定要写

if(a.length()+b.length()!=c.length()){
            cout<<"No\n";
            continue;
 }

否则例如     a:aaa     b:bbb     c:aaabbbx 的情况就会出错

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <cstring>
#define rep1(i,s,e,c) for(int i=s;i<e;i=i+c)
#define rep2(i,s,e,c) for(int i=s;i<=e;i=i+c)
#define rep3(i,e,s,c) for(int i=e;i>=s;i=i-c)
using namespace std;
typedef long long ll;
const int MAX=2e5+1;
const int MOD=1e9+7;
int dp[2005][2005];
int main()
{
    string a,b,c;
    while(cin>>a>>b>>c){
    	if(a.length()+b.length()!=c.length()){
    		cout<<"No\n";
    		continue;
		}
    	memset(dp,0,sizeof(dp));
    	dp[0][0]=1;
    	for(int i=0;i<=a.length();i++){
    		for(int j=0;j<=b.length();j++){
    			if(a[i]==c[i+j]){
    				dp[i+1][j]|=dp[i][j];
				}
				if(b[j]==c[i+j]){
					dp[i][j+1]|=dp[i][j];
				}
			}
		}
		if(dp[a.length()][b.length()]==1){
			cout<<"Yes\n";
		}
		else cout<<"No\n";
	}
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值