【题 目】
给定三个字符串str1、str2和aim。如果aim包含且仅包含来⾃自str1和str2的所有字
符,⽽而且在aim中属于str1的字符之间保持原来在str1中的顺序,属于str2的字符
之间保持原来在str2中的顺序,那么称aim是str1和str2的交错组成。实现⼀一个函
数,判断aim是否是str1和str2交错组成。
【举例】
str1=“AB”,str2=“12”。那么“AB12”、“A1B2”、“A12B”、“1A2B”和“1AB2”等等都
是str1和str2交错组成。
【难度】
校★★★☆
【解答】
如果str1的⻓长度为M,str2的⻓长度为N,经典动态规划的⽅方法可以达到时间复杂度O(M*N),额
外空间复杂度O(M*N)。如果结合空间压缩的技巧可以把额外空间复杂度减⾄至O(min{M,N})。
先来介绍经典动态规划的⽅方法。⾸首先aim如果是str1和str2的交错组成,aim的⻓长度⼀一定是M
+N,否则直接返回false。然后⽣生成⼤大⼩小为(M+1)*(N+1)布尔类型的矩阵dp,dp[i][j]的值代表
aim[0..i+j-1]能否被str1[0..i-1]和str2[0..j-1]交错组成。计算dp矩阵的时候,是从左到右再
从上到下的计算的,dp[M][N]也就是dp矩阵中最右下⾓角的值,就表⽰示aim整体能否被str1整
体和str2整体交错组成,也就是最终结果。具体说明dp矩阵每个位置的值是如何计算。
1,dp[0][0]=true。aim为空串时,当然可以被str1为空串和str2为空串交错组成。
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,否则令dp[i][0]=false。
3,矩阵dp第⼀一⾏行即dp[0][0..N-1]。dp[0][j]表⽰示aim[0..j-1]能否只被str2[0..j-1]交错组成。
如果aim[0..j-1]等于str1[0..j-1],则令dp[i][0]=true,否则令dp[i][0]=false。
4,对于其他位置(i,j),dp[i][j]的值由下⾯面的情况决定。
1)dp[i-1][j]代表aim[0..i+j-2]能否被str1[0..i-2]和str2[0..j-1]交错组成,如果可以,
那么如果再有str1[i-1]等于aim[i+j-1],说明str1[i-1]⼜又可以作为交错组成aim[0..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]交错组成,如果可以,
那么如果再有str2[j-1]等于aim[i+j-1],说明str1[j-1]⼜又可以作为交错组成aim[0..i+j-1]的最
后⼀一个字符。令dp[i][j]=true。
给定三个字符串str1、str2和aim。如果aim包含且仅包含来⾃自str1和str2的所有字
符,⽽而且在aim中属于str1的字符之间保持原来在str1中的顺序,属于str2的字符
之间保持原来在str2中的顺序,那么称aim是str1和str2的交错组成。实现⼀一个函
数,判断aim是否是str1和str2交错组成。
【举例】
str1=“AB”,str2=“12”。那么“AB12”、“A1B2”、“A12B”、“1A2B”和“1AB2”等等都
是str1和str2交错组成。
【难度】
校★★★☆
【解答】
如果str1的⻓长度为M,str2的⻓长度为N,经典动态规划的⽅方法可以达到时间复杂度O(M*N),额
外空间复杂度O(M*N)。如果结合空间压缩的技巧可以把额外空间复杂度减⾄至O(min{M,N})。
先来介绍经典动态规划的⽅方法。⾸首先aim如果是str1和str2的交错组成,aim的⻓长度⼀一定是M
+N,否则直接返回false。然后⽣生成⼤大⼩小为(M+1)*(N+1)布尔类型的矩阵dp,dp[i][j]的值代表
aim[0..i+j-1]能否被str1[0..i-1]和str2[0..j-1]交错组成。计算dp矩阵的时候,是从左到右再
从上到下的计算的,dp[M][N]也就是dp矩阵中最右下⾓角的值,就表⽰示aim整体能否被str1整
体和str2整体交错组成,也就是最终结果。具体说明dp矩阵每个位置的值是如何计算。
1,dp[0][0]=true。aim为空串时,当然可以被str1为空串和str2为空串交错组成。
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,否则令dp[i][0]=false。
3,矩阵dp第⼀一⾏行即dp[0][0..N-1]。dp[0][j]表⽰示aim[0..j-1]能否只被str2[0..j-1]交错组成。
如果aim[0..j-1]等于str1[0..j-1],则令dp[i][0]=true,否则令dp[i][0]=false。
4,对于其他位置(i,j),dp[i][j]的值由下⾯面的情况决定。
1)dp[i-1][j]代表aim[0..i+j-2]能否被str1[0..i-2]和str2[0..j-1]交错组成,如果可以,
那么如果再有str1[i-1]等于aim[i+j-1],说明str1[i-1]⼜又可以作为交错组成aim[0..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]交错组成,如果可以,
那么如果再有str2[j-1]等于aim[i+j-1],说明str1[j-1]⼜又可以作为交错组成aim[0..i+j-1]的最
后⼀一个字符。令dp[i][j]=true。
3)如果情况1)和情况2)都不满⾜足,令dp[i][j]=false。
#include<vector>
using namespace std;
class Mixture {
public:
bool chkMixture(string A, int n, string B, int m, string C, int v) {
// write code here
if(n+m!=v) return false;
vector<bool> dp;
string shorts,longs,aim;
aim = C;
if(n<m) {dp = vector<bool>(n+1,false);shorts = A;longs = B;}
else {dp = vector<bool>(m+1,false);shorts = B;longs = A;}
dp[0] = true;
for(int i = 1;i<=shorts.size();i++){
if(shorts[i-1]!=aim[i-1]){
break;
}
dp[i] = true;
}
for (int i = 1; i <= longs.size(); i++) {
for (int j = 1; j <= shorts.size(); j++) {
if ((longs[i - 1] == aim[i + j - 1] && dp[j])
|| (shorts[j - 1] == aim[i + j - 1] && dp[j - 1])) {
dp[j] = true;
} else {
dp[j] = false;
}
}
}
return dp[shorts.size()];
}
};