题意:给你三个字符串,问你能否由前两个合成第三个,且要求不改变前两个字符串的顺序。题目保证第三个字符串的长度为前两个字符串的长度之和。
题解:此题用暴力,深搜都可以过(数据太水)。这里给出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。至于初始化根据状态转移方程就很容易写出来了。
AC代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 const int maxN=205; 6 char s1[maxN],s2[maxN],sum[maxN+maxN]; 7 bool dp[maxN][maxN]; 8 bool solve(){ 9 int i,j; 10 int len1=strlen(s1+1); 11 int len2=strlen(s2+1); 12 memset(dp,false,sizeof(dp)); 13 for(i=1;i<=len1;i++) 14 if(s1[i]==sum[i])dp[i][0]=true; 15 for(i=1;i<=len2;i++) 16 if(s2[i]==sum[i])dp[0][i]=true; 17 for(i=1;i<=len1;i++) 18 for(j=1;j<=len2;j++) 19 if(dp[i-1][j]&&s1[i]==sum[i+j]||dp[i][j-1]&&s2[j]==sum[i+j]) 20 dp[i][j]=true; 21 if(dp[len1][len2])return true; 22 return false; 23 } 24 int main() 25 { 26 int T,cas=0; 27 scanf("%d",&T); 28 while(T--){ 29 scanf("%s %s %s",s1+1,s2+1,sum+1); 30 printf("Data set %d: ",++cas); 31 if(solve())printf("yes\n"); 32 else printf("no\n"); 33 } 34 return 0; 35 }