http://acm.hdu.edu.cn/showproblem.php?pid=5707
Problem Description
Given three strings a, b and c, your mission is to check whether c is the combine string of a and b.
A string c is said to be the combine string of a and b if and only if c can be broken into two subsequences, when you read them as a string, one equals to a, and the other equals to b.
For example, "adebcf’’ is a combine string of "abc’’ and "def’’.
Input
Input file contains several test cases (no more than 20). Process to the end of file.
Each test case contains three strings a, b and c (the length of each string is between 1 and 2000).
Output
For each test case, print "Yes’’, if c is a combine string of a and b, otherwise print "No’’.
Sample Input
abc
def
adebcf
abc
def
abecdf
Sample Output
Yes
No
题意
字符串匹配问题,判断 c 是否恰好由字符串 a 和 b 组成, a 为 c 的子串, b 也为 c 的子串,可以不连续。
思路
dp[i][j] 表示字符串 c 的前 i + j 位是否可以由字符串 a 的前 i 位以及字符串 b 的前 j 位组成,dp[i][j]=true 表示是,dp[i][j]=false 表示不是,则 dp[i][j] 可以由 dp[i - 1][j] 和 dp[i][j - 1] 转移过来。
如果 dp[i][j] 由 dp[i-1][j] 转移而来,那么应该满足:dp[i - 1][j] 是 true 且 a 的第 i 个字符必须等于 c 的第 i + j 个字符。
如果 dp[i][j] 由 dp[i][j-1] 转移而来, 那么应该满足:dp[i][j - 1] 是 true 且 b 的第 j 个字符必须等于c 的第 i + j 个字符。
状态转移方程:
if(can[i-1][j]&&a[i]==c[i+j]&&i>0) can[i][j]=true;
if(can[i][j-1]&&b[j]==c[i+j]&&j>0) can[i][j]=true;
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cctype>
#include<cstring>
#include<cstdlib>
const int maxn = 2010;
using namespace std;
bool can[maxn][maxn];
char a[maxn],b[maxn],c[maxn];
int main()
{
while(~scanf("%s",a+1)){
scanf("%s",b+1);
scanf("%s",c+1);
int la = strlen(a+1);
int lb = strlen(b+1);
int lc = strlen(c+1);
if((la+lb)!=lc){ //特判长度
printf("No\n");
continue;
}
memset(can,false,sizeof(can)); //初始化全为 false
can[0][0]=true; //没有字符时,应该看作 true
for(int i=0;i<=la;i++){
for(int j=0;j<=la;j++){
if(can[i-1][j]&&a[i]==c[i+j]&&i>0) can[i][j]=true;
if(can[i][j-1]&&b[j]==c[i+j]&&j>0) can[i][j]=true;
}
}
if(can[la][lb])
printf("Yes\n");
else printf("No\n");
}
return 0;
}