Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
For example,
Given:
s1 = "aabcc"
,
s2 = "dbbca"
,
When s3 = "aadbbcbcac"
, return true.
When s3 = "aadbbbaccc"
, return false.
这道题是判断字符串是否由另两个字符串通过字符交织生成,题目难度为Hard。
最直观的想法是通过回溯法来逐个检查s3中字符,通过记录下s1和s2中比对位置来比对s3中当前字符,如果s3中当前字符和s1比对位置字符相同,将s1比对位置加1继续比对s3中下一字符,s2同理,如果s3中当前字符和s1、s2比对位置字符都不同则向上回溯。可惜提交之后超时了,这里就不列出代码了。
回溯法行不通,可以从后向前思考,假设s1长度为m,s2长度为n,拿s3[m+n-1]和s1[m-1]、s2[n-1]进行比对,分以下三种情况:
- s3[m+n-1] == s1[m-1],如果s3前m+n-1个字符组成的字符串可以由s1前m-1个字符组成的字符串和s2交织生成,返回true;
- s3[m+n-1] == s2[n-1],如果s3前m+n-1个字符组成的字符串可以由s1和s2前n-1个字符组成的字符串交织生成,返回true;
- s3[m+n-1] != s1[m-1] && s3[m+n-1] != s2[n-1],s3不能由s1和s2交织生成。
这里用isMatch[i][j]表示s1前i个字符组成的字符串和s2前j个字符组成的字符串是否能够交织生成s3前i+j个字符组成的字符串,通过以上分析可以得出isMatch[i][j] = (isMatch[i-1][j] && s1[i-1]==s3[i+j-1]) || (isMatch[i][j-1] && s2[j-1]==s3[i+j-1]),而isMatch[0][0] == true(三个字符串都是空字符串时是显然的),这样通过动态规划就能够递推出isMatch[m][n],即最终结果。具体代码:
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
int sz1 = s1.size(), sz2 = s2.size(), sz3 = s3.size();
if(sz1 + sz2 != sz3) return false;
vector<vector<char>> isMatch(sz1+1, vector<char>(sz2+1, 0));
isMatch[0][0] = 1;
for(int i=0; i<=sz1; ++i) {
for(int j=0; j<=sz2; ++j) {
if(i && isMatch[i-1][j]) isMatch[i][j] |= (s1[i-1]==s3[i+j-1]);
if(j && isMatch[i][j-1]) isMatch[i][j] |= (s2[j-1]==s3[i+j-1]);
}
}
return isMatch[sz1][sz2];
}
};