51Nod-1006-最长公共子序列Lcs

                1006 最长公共子序列Lcs
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。

比如两个串为:
abcicba
abdkscab

ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。

Input
第1行:字符串A
第2行:字符串B
(A,B的长度 <= 1000)
Output

输出最长的子序列,如果有多个,随意输出1个。
Input示例
abcicba
abdkscab
Output示例
abca

解题思路:
对与求最长公共子序列、最长递增子序列等问题,都用动态规划来解即可,本题也不列外。

最长公共子序列的动态转移方程为:
当A[i] = B[j]时,f(i, j) = f(i-1, j-1)+1
当A[i] != B[j]是,f(i, j) = max(f(i-1, j), f(i, j-1))

当i=0,j=0的时候,进行i-1, j-1操作,会变为-1,看上去可能会出错。但是python不一样,列表里如果索引为负数,那么是为反向索引列表,即-1索引值为列表的最后一个数。

当然,本题最麻烦的地方是,什么时候输出的子序列是最长的。这个可以通过得到的动态转移的方程值进行回溯操作,具体可以看如下代码:

while True:
    try:
        A = input()
        B = input()
        la, lb = len(A), len(B)
        #初始化动态转移方程列表,这样可以造出像C语言那般的二维数组
        f=[[0 for i in range(la+1)] for j in range(lb+1)]

        #进行动态转移
        for i in range(la):
            for j in range(lb):
                if A[i] == B[j]:
                    f[i][j] = f[i-1][j-1] + 1
                else:
                    f[i][j] = max(f[i-1][j], f[i][j-1])


        i, j, k= la-1, lb-1, 0
        #ans可以看作是一个栈,因为回溯得到的子序列是反向的
        #我们把子序列压入栈中可以反向输出子序列
        ans = []
        #下面是利用得到的最大f[i][j]进行回溯操作
        while i>=0 and j>=0:
            if A[i] == B[j]:
                ans.append(A[i])
                i, j = i-1, j-1
            elif f[i-1][j] > f[i][j-1]:
                i -= 1
            else:
                j -= 1

        #输出操作
        while len(ans):
            print(ans.pop(), end='')
        print()
    except EOFError:
        break

这题代码我是以C语言改编而来,运行的时候,python比C慢的缺陷很快便体现出来了,此题C语言所花的时间仅仅只有两位数,但python花的时间到四位数。python慢归慢,但是有的时候确实比C方便实用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值