328K | 16MS | G++ | 859B | 2009-01-09 10:02:27 |
因为看到最后组合的字符串长度会等于两个字符串长度之和,以为很简单,想用
while(i<lenf||j<lens){
if(third[i+j]==first[i])
i++;
else if(third[i+j]==second[j])
j++;
else
return 0;
}
return 1;
后来发现错(因为两个字符串中会有相同的字母,如first[i]==second[i]),又想了好一阵子,再借鉴别人的做法:
1)创建一个数组f[n][m]记录第一个字符串的前n位与第二个字符串的前m位能否组合成第三个字符串的前n+m位。
2)由于最后组合的字符串长度会等于两个字符串长度之和,那么问题就简单了,可想而知,组合后的字符串最后一位一定来源于第一个字符串或者第二个字符串的最后一位。所以分解为f[n-1][m]和f[n][m-1]的子问题。
核心代码如下:
if((f[i-1][j]&&first[i]==third[i+j])||(f[i][j-1]&&second[j]==third[i+j]))
f[i][j]=1;
else
f[i][j]=0;
初始化工作:
if(first[1]!=third[1]&&second[1]!=third[1])
return 0;
else{
if(first[1]==third[1])
for(i=1;i<=lenf;i++)
f[i][0]=1;
if(second[1]==third[1])
for(i=1;i<=lens;i++)
f[0][i]=1;
}
代码如下:
#include<stdio.h>
#include<string.h>
char first[202],second[202],third[404];
bool f[202][202];
int test()
{
int i,j,lenf,lens;
lenf=strlen(&first[1]);
lens=strlen(&second[1]);
i=j=0;f[0][0]=1;
if(first[1]!=third[1]&&second[1]!=third[1])
return 0;
else{
if(first[1]==third[1])
for(i=1;i<=lenf;i++)
f[i][0]=1;
if(second[1]==third[1])
for(i=1;i<=lens;i++)
f[0][i]=1;
}
for(i=1;i<=lenf;i++)
for(j=1;j<=lens;j++){
if((f[i-1][j]&&first[i]==third[i+j])||(f[i][j-1]&&second[j]==third[i+j]))
f[i][j]=1;
else
f[i][j]=0;
}
return f[lenf][lens];
}
int main()
{
int t,caseno;
scanf("%d",&t);
for(caseno=1;caseno<=t;caseno++)
{
scanf("%s %s %s",&first[1],&second[1],&third[1]);
if(test())
printf("Data set %d: yes\n",caseno);
else
printf("Data set %d: no\n",caseno);
}
}