字符串4(动态规划实现).最长公共子序列

Description
给定两个字符串,返回两个字符串的最长公共子序列(不是最长公共子字符串),可能是多个。

Input
输入第一行为用例个数, 每个测试用例输入为两行,一行一个字符串

Output
如果没有公共子序列,不输出,如果有多个则分为多行,按字典序排序。

Sample Input 1
1
1A2BD3G4H56JK
23EFG4I5J6K7

Sample Output 1
23G456K
23G45JK

def solution(l1, l2, dp, max_value, len_1, len_2, st, s):
    while max_value > 0:
        if len_1 > 0 and len_2 > 0 and dp[len_1][len_2] == dp[len_1 - 1][len_2] and dp[len_1][len_2] == dp[len_1][len_2 - 1]:
            solution(l1, l2, dp, max_value, len_1, len_2 - 1, st, s)
            solution(l1, l2, dp, max_value, len_1 - 1, len_2, st, s)
            return
        elif len_1 > 0 and dp[len_1][len_2] == dp[len_1 - 1][len_2]:
            len_1 -= 1
        elif len_2 > 0 and dp[len_1][len_2] == dp[len_1][len_2 - 1]:
            len_2 -= 1
        else:
            st = l1[len_1] + st
            len_1 -= 1
            len_2 -= 1
            max_value -= 1
    s.add(st)


def dp_array(l1 ,l2):
    # l1充当动态规划数组的列,l2充当行
    init = [[0 for m in range(len(l2))] for n in range(len(l1))]
    init[0][0] = 1 if l1[0] == l2[0] else 0
    for i in range(1, len(l2)):
        init[0][i] = max(init[0][i - 1], 1 if l1[0] == l2[i] else 0)
    for j in range(1, len(l1)):
        init[j][0] = max(init[j - 1][0], 1 if l1[j] == l2[0] else 0)
    for p in range(1, len(l1)):
        for q in range(1, len(l2)):
            if l1[p] == l2[q]:
                init[p][q] = init[p - 1][q - 1] + 1
            else:
                init[p][q] = max(init[p - 1][q], init[p][q - 1])
    return init


if __name__ == '__main__':
    n = int(input())
    for _ in range(n):
        l1 = input().strip()
        l2 = input().strip()
        dp = dp_array(l1, l2)
        max_value = dp[-1][-1]
        s = set()
        len_1 = len(l1) - 1
        len_2 = len(l2) - 1
        st = ""
        solution(l1, l2, dp, max_value, len_1, len_2, st, s)
        for i in sorted(list(s)):
            print(i)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值