LeetCode 97. Interleaving String
参考网址:[1]https://www.youtube.com/watch?v=HmAF9xeS_2I
[2]http://www.cnblogs.com/grandyang/p/4298664.html
【初始化】这道题的大前提是字符串s1和s2的长度和必须等于s3的长度,如果不等于,肯定返回false。当s1和s2是空串的时候,s3必然是空串,则返回true。所以直接给dp[0][0]赋值true,然后若s1和s2其中的一个为空串的话,那么另一个肯定和s3的长度相等,则按位比较,若相同且上一个位置为True,赋True,其余情况都赋False,这样的二维数组dp的边缘就初始化好了。
在任意非边缘位置dp[i][j]时,它的左边或上边有可能为True或是False,两边都可以更新过来,只要有一条路通着,那么这个点就可以为True。那么我们得分别来看,如果左边的为True,那么我们去除当前对应的s2中的字符串s2[j - 1] 和 s3中对应的位置的字符相比(计算对应位置时还要考虑已匹配的s1中的字符),为s3[j - 1 + i], 如果相等,则赋True,反之赋False。 而上边为True的情况也类似,所以可以求出递推公式为:
dp[i][j] = (dp[i - 1][j] && s1[i - 1] == s3[i - 1 + j]) || (dp[i][j - 1] && s2[j - 1] == s3[j - 1 + i])
其中dp[i][j] 表示的是 s2 的前 i 个字符和 s1 的前 j 个字符是否匹配 s3 的前 i+j 个字符,根据以上分析,可写出代码如下:
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
if (s1.size() + s2.size() != s3.size()) return false;
int n1 = s1.size();
int n2 = s2.size();
vector<vector<bool> > dp(n1 + 1, vector<bool> (n2 + 1, false));
dp[0][0] = true;
for (int i = 1; i <= n1; i++)
dp[i][0] = dp[i - 1][0] && (s1[i - 1] == s3[i - 1]);
for (int j = 1; j <= n2; j++)
dp[0][j] = dp[0][j - 1] && (s2[j - 1] == s3[j - 1]);
for (int i = 1; i <= n1; i++) {
for (int j = 1; j <= n2; j++) {
dp[i][j] = (dp[i - 1][j] && s1[i - 1] == s3[i - 1 + j])
|| (dp[i][j - 1] && s2[j - 1] == s3[j - 1 + i]);
}
}
return dp[n1][n2];
}
};