题意:给你三个字符串,问你能否由前两个合成第三个,且要求不改变前两个字符串的顺序。题目保证第三个字符串的长度为前两个字符串的长度之和。
题解:此题用暴力,深搜都可以过(数据太水)。这里给出DP的解法。
dp[i][j](bool 型)代表第一个字符串的前i个字符和第二个字符串的前j个字符能否合成第三个字符串的前i+j个字符串。
则状态转移方程为:
1 if(dp[i-1][j]&&s1[i]==sum[i+j]||dp[i][j-1]&&s2[j]==sum[i+j]) 2 dp[i][j]=true;
对于状态方程的解释:
1.若第一个字符串的前i-1个字符和第二个字符串前j个字符可以合成第三个字符串的前i+j-1个字符,则如果第一个字符串的第i个字符和第三个字符的第i+j个字符相同,那么第一个字符串的前i个加上第二个字符串的前j个字符可以合成第三个字符串的前i+j个字符,则dp[i][j]就等于true,否则dp[i][j]=false。
2.若第一个字符串的前i个字符和第二个字符串前j-1个字符可以合成第三个字符串的前i+j-1个字符,则如果第二个字符串的第j个字符和第三个字符的第i+j个字符相同,那么第一个字符串的前i个加上第二个字符串的前j个字符可以合成第三个字符串的前i+j个字符,则dp[i][j]就等于true,否则dp[i][j]=false。至于初始化根据状态转移方程就很容易写出来了。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int maxN=205; char s1[maxN],s2[maxN],sum[maxN+maxN]; bool dp[maxN][maxN]; bool solve(){ int i,j; int len1=strlen(s1+1); int len2=strlen(s2+1); memset(dp,false,sizeof(dp)); for(i=1;i<=len1;i++) if(s1[i]==sum[i])dp[i][0]=true; for(i=1;i<=len2;i++) if(s2[i]==sum[i])dp[0][i]=true; for(i=1;i<=len1;i++) for(j=1;j<=len2;j++) if(dp[i-1][j]&&s1[i]==sum[i+j]||dp[i][j-1]&&s2[j]==sum[i+j]) dp[i][j]=true; if(dp[len1][len2])return true; return false; } int main() { int T,cas=0; scanf("%d",&T); while(T--){ scanf("%s %s %s",s1+1,s2+1,sum+1); printf("Data set %d: ",++cas); if(solve())printf("yes\n"); else printf("no\n"); } return 0; }