题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5707
题目解析:
按题意,三个字符串 a,b,c 求c是否能由a,b按顺序构成
定义数组 dp[2000][2000],
dp[i][j] 代表用字符串a的前i位和字符串b的前j位,可以组成字符串c的前i+j位
则递推公式(状态转换公式):
dp[i][j] = ( dp[i-1][j] && a[i-1]==c[i+j-1] ) || ( dp[i][j-1] && b[j-1]==c[i+j-1] )
递推公式的含义是:如果 a 的前 i 位和 b 的前 j 位能构成 c 的前 i+j 位的话,则只有两种可能:
1、 a[i-1] == c[i+j-1] 即a的第i个字符等于c的第i+j个字符
并且 dp[i-1][j] == true 即 a 的前 i-1 个字符和 b 的前 j 位字符能构成 c 的前 i+j-1 位
2、 b[j-1] == c[i+j-1] 即b的第j个字符等于c的第i+j个字符
并且 dp[i][j-1] == true 即 a 的前 i 个字符和 b 的前 j-1 个字符能构成 c 的前 i+j-1 位
程序从初始化 dp[0][0]=true 开始递推
#include <algorithm>
#include <iostream>
using namespace std;
char a[2000], b[2000], c[2000];
bool dp[2001][2001];
int main() {
int i, j, aL, bL, cL;
while (cin >> a >> b >> c) {
memset(dp, 0, sizeof(dp));
aL = strlen(a);
bL = strlen(b);
cL = strlen(c);
if (aL + bL != cL) {
cout << "No" << endl;
continue;
}
for (i = 0; i <= aL; i++)
for (j = 0; j <= bL; j++) {
if (i == 0 && j == 0) {
dp[i][j] =
true; // dp[0][0] a的前0个和b的前0个一定组成C的前0ge
}
if (i > 0) {
dp[i][j] |= (dp[i - 1][j] && a[i - 1] == c[i + j - 1]);
}
if (j > 0) {
dp[i][j] |= (dp[i][j-1] && b[j - 1] == c[i + j - 1]);
}
}
if (dp[aL][bL])
cout << "Yes" << endl;
else
cout << "No" << endl;
}
}