dp基础之双序列型交错形成字符串

问题:给定三个字符串A,B,X,判断X是否是由A,B的字符交错而形成(True/False)
例:A = ['a','a','b','c','c'],B = ['d','b','b','a','c']
X = ["a","a",'d',"b",'b',"c",'b',"c",'a','c']
输出:True(双引号是A中的字符,单引号是B中的字符)

问题分析:令m = len(A),n = len(B),x = len(X),若x != m+n,则X肯定不能由A、B交错形成。
否则,考虑最后一步,X由A、B交错形成,X的最后一个字符(X[m+n-1]),
    case1:是A[m-1],则X[0,...,m+n-2]由A[0,...,m-2]和B[0,...n-1]交错形成
    case2:是B[n-1],则X[0,...,m+n-2]由A[0,...,m-1]和B[0,...n-2]交错形成
子问题:本来要求X[0,...,m+n-1]是否由A[0,...,m-1]和B[0,...n-1]交错形成
       现在要求则X[0,...,m+n-2]是否由A[0,...,m-2]和B[0,...n-1]交错形成;
                X[0,...,m+n-2]是否由A[0,...,m-1]和B[0,...n-2]交错形成。
转移方程:设f[i][j]表示X的前i+j个字符X[0,...,i+j-1]是否
          由A的前i个字符A[0,...,i-1]和B的前j个字符B[0,...,j-1]个字符交错而成

    则f[i][j] = (f[i-1][j] | X[i+j-1] = A[i-1]) OR (f[i][j-1] | X[i+j-1] = B[j-1])
                          case1                 OR               case2
初始情况:

    f[0][0] = True,空字符可以由空字符形成。
边界情况:
    i = 0,则只考虑case2,
    j = 0,则只考虑case1
计算顺序:
    f[0][0]...f[0][n]
    .

    .
    .
    f[m][0]...f[m][n]
答案:f[m][n]

时间复杂度O(mn),空间复杂度O(mn),可以优化到O(n)

 

代码及注释如下:

 

def interleaving_str(A,B,X):
    m , n = len(A) , len(B)
    if len(X) != m+n:
        return False
    f = [[False for i in range(n+1)] for j in range(m+1)]
    
    for i in range(m+1):
        for j in range(n+1):
            #初始情况,f[0][0] = False,其实没必要,创建的时候就已经设好了
            if i == 0 and j == 0:
                f[i][j] = True
                continue
            f[i][j] = False
            #case1:f[i-1][j] | X[i+j-1] = A[i-1]
            if  i > 0 and X[i+j-1] == A[i-1]:
                f[i][j] = f[i][j] or f[i-1][j]
            #case2:f[i][j-1] | X[i+j-1] = B[j-1]
            if  j > 0 and X[i+j-1] == B[j-1]:
                f[i][j] = f[i][j] or f[i][j-1]
    return f[m][n]

A = ['a','a','b','c','c']
B = ['d','b','b','a','c']
X = ["a","a",'d',"b",'b',"c",'b',"c",'a','c']
print(interleaving_str(A,B,X))
#结果:True


    未完待续。。。空间优化,和之前类似old new数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值