题目:字符串的交错组成
给定三个字符串 str1, str2 和 aim,如果 aim 包含仅包含来自 str1 和 str2的所有字符,而且在 aim 中属于str1的字符之间保持原来在 str1 的顺序,属于str2的字符之间保持原来 str2 的顺序,那么称 aim 是 str1 和 str2的交错组成。实现一个函数,判断aim是否是 str1 和 str2 交错组成。
-----------------------------------------------------------------------------------------------------------------
说明:
原文作者利用Java进行实现,这里运用C++进行实现,供大家参考。
举例:
str1 = "AB", str2 = "12",那么"AB12"、"A1B2"、"A12B"、"12AB" 和 "1AB2"都是 str1 和 str2的交错组成。
解答:
如果str1的长度为M, str2的长度为N,可以利用经典的动态规划的方法可以达到时间复杂度为O(MN), 额外空间复杂度为O(MN)。
方法:aim的长度一定为 M+N,否则返回 false. 生成(M+1)x(N+1)的布尔类型的矩阵dp,
dp[i][j]表示 aim[0...i+j-1] 能否被 str1[0...i-1] 和 str2[0...j-1]交错组成。
从左到右,从上到下计算,结果即为 dp[M][N]的值
更新策略:
1. dp[0][0] = true;
2. 矩阵dp第一列 dp[0...M-1][0] , dp[i][0] 表示 aim[0...i-1] 能否被 str1[0...i-1]组成,若
aim[0...i-1] == str1[0...i-1],dp[i][0] = true ;
3. 矩阵dp第一行 dp[0][0...N-1],dp[0][j] 表示 aim[0...j-1] 能否被 str2[0...j-1]组成,若
aim[0...j-1] == str2[0..j-1], dp[0][j] = true;
4. 其他位置的更新:
dp[i][j] 的更新依赖于 dp[i-1][j] 与 dp[i][j-1]的结果,现做以下判断:
(1) dp[i-1][j] 代表 aim[0..i+j-2] 能否被 str1[0...i-2] 和 str2[0...j-1]交错组成,如果可以(dp[i-1][j] = true),再在满足
str1[i-1] == aim[i+j-1] 则 dp[i][j] = true.
(2) dp[i][j-1] 代表 aim[0..i+j-2] 能否被 str1[0...i-1] 和 str2[0...j-2]交错组成,如果可以 (dp[i][j-1] = true),再在满足
str2[j-1] == aim[i+j-1] 则 dp[i][j] = true.
(3) 若(1)(2)均不满足,则 dp[i][j] = false.
-------------------------------------------------------------------------------------------------------------------------------------
代码如下:
// 字符串的交错组成<动态规划> <复杂度0(M*N)>
#include
using namespace std;
bool isCross1(string str1, string str2, string aim);
int main(){
string str1, str2, aim;
cout<<"第一个字符串:"; cin >> str1;
cout<<"第二个字符串:"; cin >> str2;
cout<<"目标字符串:"; cin >> aim;
bool result = isCross1(str1, str2, aim);
cout<<"判断结果为:"<< result;
return 0;
}
bool isCross1(string str1,string str2, string aim){
int row = str1.size() + 1;
int col = str2.size() + 1;
vector> dp(row, vector(col, false));
if(aim.size() != (str1.size()+str2.size())){
return false;
}
dp[0][0] = true;
for(int i = 1; i < row; i++){
if(str1[i-1] != aim[i-1]){
break;
}
dp[i][0] = true;
}
for(int j = 1; j < col; j++){
if(str2[j-1] != aim[j-1]){
break;
}
dp[0][j] = true;
}
for(int i = 1; i < row; i++){
for(int j = 1; j < col; j++){
if(str1[i-1] == aim[i+j-1] && dp[i-1][j]){
dp[i][j] = true;
}
if(str2[j-1] == aim[i+j-1] && dp[i][j-1]){
dp[i][j] = true;
}
}
}
return dp[row - 1][col - 1];
}
/* input
ABCD
1234
A12B34CD
*/
/*
1
*/
编译器:codeblocks
输入:
输出: