题目链接:Interleaving String

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.

这道题的要求是检测字符串s3是否由s1和s2交错生成。

这是一道动态规划的题目,用dp[i, j]表示s1的前i个字符和s2的前j个字符能否通过交错生成s3的前i+j个字符。

至于dp数组的初值,当j等于0的时候,dp[i, 0]的值取决于dp[i-1, 0]是否为真以及s1[i-1]是否等于s3[i-1],即

  • dp[i][0] = dp[i-1][0] && s1[i-1] == s3[i-1]

同理,当i等于0的时候:

  • dp[0][j] = dp[0][j-1] && s2[j-1] == s3[j-1]

至于递推公式,取决于当期读到的字符是否等于s3中对应的字符相同:

  • 如果s1[i-1]与s3[i+j-1]相同,说明当前位置s1可以进行匹配,因此如果dp[i-1, j]也为真,dp[i, j]就为真。
  • 如果s2[j-1]与s3[i+j-1]相同,说明当前位置s2可以进行匹配,因此如果dp[i, j-1]也为真,dp[i, j]就为真。
综上所述,递推公式为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])。

注意一下,如果s1的长度加上s2的长度不等于s3的长度,则直接返回false即可。

时间复杂度:O(nm)

空间复杂度:O(nm)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution
{
public:
    bool isInterleave(string s1, string s2, string s3)
    {
        int l1 = s1.size(), l2 = s2.size(), l3 = s3.size();

        if(l3 != l1 + l2)
            return false;

        vector<vector<bool> > dp(l1 + 1, vector<bool>(l2 + 1, false));

        dp[0][0] = true;
        for(int i = 1; i <= l1; ++ i)
            dp[i][0] = dp[i - 1][0] && s1[i - 1] == s3[i - 1];
        for(int j = 1; j <= l2; ++ j)
            dp[0][j] = dp[0][j - 1] && s2[j - 1] == s3[j - 1];

        for(int i = 1; i <= l1; ++ i)
            for(int j = 1; j <= l2; ++ j)
                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[l1][l2];
    }
};

这道题还有人给出了BFS的方法。