递归与动态规划---字符串的交错组成

【题目】

  给定三个字符串str1, str2和aim, 如果aim包含且仅包含str1和str2的所有字符,而且在aim中属于str1的字符之间保持原来在str1中的顺序,属于str2的字符之间保持原来在str2中的顺序,那么称aim是str1和str2的交错组成。实现一个函数,判断aim是否是str1和str2的交错组成。

【举例】

  str1 = “AB”, str2 = “12”。那么”AB12”, “A1B2”, “A12B”, “1A2B”, “1AB2”等都是str1和str2的交错组成。

【基本思路】

  假设str1的长度为N,str2的长度为M,生成(N+1)*(M+1)的dp矩阵,为什么是N+1,M+1,因为我们需要在字符串的开头添加一个空字符的特殊情况,dp[i][j]的值代表aim[0…i+j-1]能否被str1[0…i-1]和str2[0…j-1]交错组成,dp[i][j]的值计算如下:

  1. 矩阵的第一行表示能否只用str2[0…j-1]交错组成aim[0…j-1],如果str2[0…j-1]等于aim[0…j-1],则令dp[0][j] = True,否则为False

  2. 矩阵的第一列同上,如果str1[0…i-1]等于aim[0…i-1],则令dp[i][0] = True,否则为False

  3. 矩阵的其余位置由以下情况决定:
    1)dp[i-1][j]代表aim[0…i+j-2]能否被str1[0…i-2]和str2[0…j-1]交错组成,如果可以,那么如果再有str1[i-1]等于aim[i+j-1],说明str1[i-1]又可以作为交错组成aim[0…i+j-1]的最后一个字符。令dp[i][j] = True

    2)dp[i][j-1]代表aim[0…i+j-2]能否被str2[0…j-2]和str1[0…i-1]交错组成,如果可以,那么如果再有str2[j-1]等于aim[i+j-1],说明str2[j-1]又可以作为交错组成aim[0…i+j-1]的最后一个字符。令dp[i][j] = True

    3)如果上述情况不满足,令dp[i][j] = False

下面是使用python3.5实现的代码

#字符串的交错组成
#经典动态规划方法
def isCross1(str1, str2, aim):
    if str1 == None or str2 == None or aim == None or len(str1)+len(str2) != len(aim):
        return False
    dp = [[False for i in range(len(str2)+1)] for j in range(len(str1)+1)]
    dp[0][0] = True
    for i in range(1, len(str1)+1):
        if str1[i-1] != aim[i-1]:
            break
        dp[i][0] = True
    for j in range(1, len(str2)+1):
        if str2[j-1] != aim[j-1]:
            break
        dp[0][j] = True
    for i in range(1, len(str1)+1):
        for j in range(1, len(str2)+1):
            if (dp[i-1][j] == True and str1[i-1] == aim[i+j-1]) or (dp[i][j-1] == True and str2[j-1] == aim[i+j-1]):
                dp[i][j] = True
    return dp[-1][-1]

#动态规划+空间压缩
def isCross2(str1, str2, aim):
    if str1 == None or str2 == None or aim == None or len(str1)+len(str2) != len(aim):
        return False
    longs = str1 if len(str1) >= len(str2) else str2
    shorts = str1 if len(str1) < len(str2) else str2
    dp = [False for i in range(len(shorts)+1)]
    dp[0] = True
    for i in range(1, len(dp)):
        if shorts[i-1] != aim[i-1]:
            break
        dp[i] = True
    for i in range(1, len(longs)+1):
        for j in range(1, len(shorts)+1):
            if (dp[j-1] == True and shorts[j-1] == aim[i+j-1]) or (dp[i] == True and longs[i-1] == aim[i+j-1]):
                dp[j] = True
    return dp[-1]

你可能感兴趣的:(数据结构与算法)