最长公共子序列-Python-动态规划

1.题目内容

题名为:最长公共子序列。
题目要求:
1.用动态规划算法思想设计最长公共子序列问题求解算法,并且对给定的数据(分两类:统一和自选)进行验证。
2.要求分析算法的时间复杂性。
3.与穷举算法,直接递归法,备忘录法进行对比并且形成分析报告。

2.算法分析

1.算法原理:

字符串X,长度为m,从1开始数;
字符串Y,长度为n ,从1开始数;
Xi=﹤x1,⋯,xi﹥即X序列的前i个字符(1≤i≤m)
Yj=﹤y1,⋯,yj﹥即Y序列的前j个字符 (1≤j≤n)
LCS(X , Y) 为字符串X和Y的最长公共子序列,即为Z=﹤z1,⋯,zk﹥

若xm=yn(最后一个字符相同),则:
Xm与Yn的最长公共子序列Zk的最后一个字符必定为xm
zk=xm=yn
LCS(Xm,Yn) = LCS(Xm-1,Yn-1)+xm

若xm≠yn,则:
LCS(Xm,Yn)= max{LCS(Xm-1,Yn),LCS(Xm,Yn-1)}

2.算法实现步骤:
1)先找LCS的长度:

a=<x1,x2,x3…xn>
b=<y1,y2,y3…ym> (两个序列)

创建一个二维数组c[i][j],用来存放LCS的长度
c[0][j],c[i][0]初始化为0,因为任何字符串和一个空字符串的lcs 都是为0。
从a[0]开始,依次和b[i]对比,

(1)如果a[j]和b[j]相等,那么a[i][j]==a[i-1]j-1

(2)如果a[j]和b[i]不相等,那么a[i][j]就和a[i-1][j],a[i][j-1]比较,那个大就填那个值。

依此类推,最后填出的表右下角的值为LCS的长度
[0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 1, 1, 1, 1, 1]
[0, 0, 1, 1, 1, 2, 2, 2]
[0, 0, 1, 2, 2, 2, 2, 2]
[0, 1, 1, 2, 2, 2, 3, 3]
[0, 1, 2, 2, 3, 3, 3, 4]
[0, 1, 2, 2, 3, 3, 4, 4]

2)再找LCS本身:
为了查找方便,在比较a[i]b[j]时,另创一个数组记录每个位置的动作。如果相等,此位置为“ok”,如果不相等,上面的大为“up”,左面的大为“left”。

最后从c[i][j]开始看,如果flag[i,j]”ok”,那么lcs的最后一个就是a[i-],此时a[i-]b[j-],如果flag[i,j][up],j-1 重新看flag[i,j]的值,如果flag[i,j]”left”,则i-1,在看flag。

3.算法时间复杂性

a序列 b序列 LCS 时间
18 25 6 0.00024454
15 20 5 0.0001738
50 50 11 0.0012632
100 100 30 0.0046937
500 500 161 0.13901399999
1000 1000 320 0.650319700

3.算法调试
1.在计算时间复杂性时,遇到在500以上数据量时会报错
(maximum recursion depth exceeded in comparison)因为python默认的递归深度是很有限的(默认是1000),因此当递归深度超过999的样子,就会引发这样的一个异常。此时在代码首部加入更改递归深度的代码即可解决。
import sys
sys.setrecursionlimit(100000)

4.算法比较

1.穷举法:将a[],b[]两个字符串的所有字符串求出,并将这些字符串相互比较知道找到最长公共子序列为止,当字符串长度很大时,所耗时间非常大。
2.直接递归法:当a[]b[]两个字符串相对应的位置的字符串相同时,则直接求下一个位置,当不同时取两种情况中的最大值。时间复杂都线性增长。
3.备忘录算法是从顶向下计算最优解的思想,备忘录方法的控制结构与直接递归方法的控制结构相同,但备忘录方法用一个表格来保存已解决的子问题的答案,避免了相同问题的重复求解。

5.代码

import time
import random
import string
import sys
sys.setrecursionlimit(100000)

#找到有几个lcs
q
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值