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;
}