Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
Example 1:
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac" Output: true
Example 2:
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc" Output: false
题解:判断当前字符串能否由给出的两个子串组成,本题关键在于定义子问题,实际上这里子问题不是在给定的串而是两个子串,也就是通过两个子串的状态dp[i][j]来表示所组成的串是否等于给的串的前i+j+1,这里局部是可以转移到下一个状态的,只要判断下个字符是否等于给定的字符串的字符即可,以后先不要把给定的东西都放进dp空间,先从部件入手,一步一步构成全局,这里还需注意刚开始可能选不到其中一个,也就是i指向的第一个字符串位置为0,所以用0表示每个字符串前的一个空位置,代码:
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
if(s1.size()+s2.size()!=s3.size()) return false;
vector<vector<bool>> dp(s1.size()+1,vector<bool>(s2.size()+1,false));
for(int i=0;i<=s1.size();i++){
for(int j=0;j<=s2.size();j++){
if(i==0&&j==0) dp[i][j]=true;
else if(i==0) dp[i][j]=s2[j-1]==s3[j-1]&&dp[i][j-1];
else if(j==0) dp[i][j]=s1[i-1]==s3[i-1]&&dp[i-1][j];
else dp[i][j]=(s1[i-1]==s3[i+j-1]&&dp[i-1][j])||(s2[j-1]==s3[i+j-1]&&dp[i][j-1]);
}
}
return dp[s1.size()][s2.size()];
}
};
可以进一步优化空间,dp降成一维,因为当前的dp[i][j]只跟前一层的j或者当前层的j-1有关所以去掉i在从0开始更新的顺序下不影响结果。
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
if(s1.size()+s2.size()!=s3.size()) return false;
vector<bool> dp(s2.size()+1,false);
for(int i=0;i<=s1.size();i++){
for(int j=0;j<=s2.size();j++){
if(i==0&&j==0) dp[j]=true;
else if(i==0) dp[j]=s2[j-1]==s3[j-1]&&dp[j-1];
else if(j==0) dp[j]=s1[i-1]==s3[i-1]&&dp[j];
else dp[j]=(s1[i-1]==s3[i+j-1]&&dp[j])||(s2[j-1]==s3[i+j-1]&&dp[j-1]);
}
}
return dp[s2.size()];
}
};