Problem description:
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.
Analysis:
Here is good explanation:
dp[i][j] means if s3 is interleaving at (i + j) th position,
when s1 is at i th position and s2 is at j th position;
0 th position means empty string;
It’s like in a chessboard, the problem acutually is seeking a path from
top - left corner to the bottom right corner.
bool isInterleave(string s1, string s2, string s3)
{
int m = s1.size();
int n = s2.size();
int k = s3.size();
if (m + n != k) return false;
bool dp[m + 1][n + 1] = {false};
for (int i = 0; i <= m; ++i)
for (int j = 0; j <= n; ++j)
{
if (i == 0 && j == 0)
dp[i][j] = true;
else if (i == 0)
dp[i][j] = dp[i][j - 1] && s3[i + j - 1] == s2[j - 1];
else if (j == 0)
dp[i][j] = dp[i - 1][j] && s1[i - 1] == s3[i + j - 1];
else dp[i][j] = (dp[i][j - 1] && s3[i + j - 1] == s2[j - 1]) || (dp[i - 1][j] && s1[i - 1] == s3[i + j - 1]);
}
return dp[m][n];
}
Here is a solution using 1D table:
bool isInterleave(string s1, string s2, string s3) {
int m = s1.length(), n = s2.length(), l = s3.length();
if (m > n) return isInterleave(s2, s1, s3);
if (l != m + n) return false;
bool *dp = new bool[m + 1]();
dp[0] = true;
for (int i = 1; i <= m; i++)
dp[i] = dp[i - 1] && s3[i - 1] == s1[i - 1];
for (int j = 1; j <= n; j++) {
dp[0] = dp[0] && s3[j - 1] == s2[j - 1];
for (int i = 1; i <= m; i++)
dp[i] = (dp[i - 1] && s3[i + j - 1] == s1[i - 1]) || (dp[i] && s3[i + j - 1] == s2[j - 1]);
}
return dp[m];
}