0011算法笔记动态规划最长公共子序列问题LCS文档格式.docx

上传人:b****6 文档编号:22031595 上传时间:2023-02-02 格式:DOCX 页数:20 大小:199.71KB
下载 相关 举报
0011算法笔记动态规划最长公共子序列问题LCS文档格式.docx_第1页
第1页 / 共20页
0011算法笔记动态规划最长公共子序列问题LCS文档格式.docx_第2页
第2页 / 共20页
0011算法笔记动态规划最长公共子序列问题LCS文档格式.docx_第3页
第3页 / 共20页
0011算法笔记动态规划最长公共子序列问题LCS文档格式.docx_第4页
第4页 / 共20页
0011算法笔记动态规划最长公共子序列问题LCS文档格式.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

0011算法笔记动态规划最长公共子序列问题LCS文档格式.docx

《0011算法笔记动态规划最长公共子序列问题LCS文档格式.docx》由会员分享,可在线阅读,更多相关《0011算法笔记动态规划最长公共子序列问题LCS文档格式.docx(20页珍藏版)》请在冰豆网上搜索。

0011算法笔记动态规划最长公共子序列问题LCS文档格式.docx

=Yn时,必须解两个子问题,即找出Xm-1和Y的一个最长公共子序列及X和Yn-1的一个最长公共子序列。

这两个公共子序列中较长者为X和Y的最长公共子序列。

设数组b[i][j]记录c[i][j]的值由哪一个子问题的解得到的,从b[m][n]开始,依其值在数组b中搜索,当b[i][j]=1时,表示Xi和Yj的最长公共子序列是由Xi-1和Yj-1的最长公共子序列在尾部加上xi所得到的子序列。

当b[i][j]=2时,表示Xi和Yj的最长公共子序列与Xi-1和Yj-1的最长公共子序列相同。

当b[i][j]=3时,表示Xi和Yj的最长公共子序列与Xi和Yj-1的最长公共子序列相同。

代码如下:

[cpp] 

viewplain 

copy

1.//3d3-1 

最长公共子序列问题 

2.#include 

"

stdafx.h"

3.#include 

<

iostream>

4.using 

namespace 

std;

5. 

6.const 

int 

7;

7.const 

6;

8. 

9.void 

output(char 

*s,int 

n);

10.void 

LCSLength(int 

m,int 

n,char 

*x,char 

*y,int 

**c,int 

**b);

11.void 

LCS(int 

i,int 

j,char 

*x,int 

12. 

13.int 

main() 

14.{ 

15. 

//X={A,B,C,B,D,A,B} 

16. 

//Y={B,D,C,A,B,A} 

17. 

char 

x[] 

{'

'

'

A'

B'

C'

D'

};

18. 

y[] 

19. 

20. 

**c 

new 

*[M+1];

21. 

**b 

22. 

for(int 

i=0;

i<

=M;

i++) 

23. 

24. 

c[i] 

int[N+1];

25. 

b[i] 

26. 

27. 

28. 

cout<

序列X:

endl;

29. 

output(x,M);

30. 

序列Y:

31. 

output(y,N);

32. 

33. 

LCSLength(M,N,x,y,c,b);

34. 

35. 

序列X、Y最长公共子序列长度为:

c[M][N]<

36. 

序列X、Y最长公共子序列为:

37. 

LCS(M,N,x,b);

38. 

39.} 

40. 

41.void 

n) 

42.{ 

43. 

i=1;

=n;

44. 

45. 

s[i]<

;

46. 

47. 

48.} 

49. 

50.void 

**b) 

51.{ 

52. 

i,j;

53. 

54. 

for(i=1;

=m;

55. 

c[i][0] 

0;

56. 

57. 

c[0][i] 

58. 

59. 

60. 

61. 

for(j=1;

j<

j++) 

62. 

63. 

if(x[i]==y[j]) 

64. 

65. 

c[i][j]=c[i-1][j-1]+1;

66. 

b[i][j]=1;

67. 

68. 

else 

if(c[i-1][j]>

=c[i][j-1]) 

69. 

70. 

c[i][j]=c[i-1][j];

71. 

b[i][j]=2;

72. 

73. 

74. 

75. 

c[i][j]=c[i][j-1];

76. 

b[i][j]=3;

77. 

78. 

79. 

80.} 

81. 

82.void 

83.{ 

84. 

if(i==0 

|| 

j==0) 

85. 

86. 

return;

87. 

88. 

if(b[i][j]==1) 

89. 

90. 

LCS(i-1,j-1,x,b);

91. 

x[i]<

92. 

93. 

if(b[i][j]==2) 

94. 

95. 

LCS(i-1,j,x,b);

96. 

97. 

98. 

99. 

LCS(i,j-1,x,b);

100. 

101.} 

LCSLength函数在计算最优值时,分别迭代X,Y构造数组b,c。

设数组每个元素单元计算耗费时间O

(1),则易得算法LCSLength的时间复杂度为O(mn)。

在算法LCS中,依据数组b的值回溯构造最优解,每一次递归调用使i,或j减小1。

从而算法的计算时间为O(m+n)。

LCS的回溯构造最优解过程如下图所示:

算法的改进:

对于一个具体问题,按照一般的算法设计策略设计出的算法,往往在算法的时间和空间需求上还可以改进。

这种改进,通常是利用具体问题的一些特殊性。

例如,在算法LCS_length和LCS中,可进一步将数组b省去。

事实上,数组元素c[i,j]的值仅由c[i-1][j-1],c[i-1][j]和c[i][j-1]三个值之一确定,而数组元素b[i][j]也只是用来指示c[i][j]究竟由哪个值确定。

因此,在算法LCS中,我们可以不借助于数组b而借助于数组c本身临时判断c[i][j]的值是由c[i-1][j-1],c[i-1][j]和c[i][j-1]中哪一个数值元素所确定,代价是Ο

(1)时间。

既然b对于算法LCS不是必要的,那么算法LCS_length便不必保存它。

这一来,可节省θ(mn)的空间,而LCS_length和LCS所需要的时间分别仍然是Ο(mn)和Ο(m+n)。

另外,如果只需要计算最长公共子序列的长度,则算法的空间需求还可大大减少。

事实上,在计算c[i][j]时,只用到数组c的第i行和第i-1行。

因此,只要用2行的数组空间就可以计算出最长公共子序列的长度。

更进一步的分析还可将空间需求减至min(m,n)。

1.//3d3-2 

**c);

LCSLength(M,N,x,y,c);

LCS(M,N,x,c);

37.} 

39.void 

40.{ 

41. 

42. 

46.} 

48.void 

**c) 

49.{ 

50. 

51. 

75.} 

77.void 

78.{ 

80. 

82. 

83. 

if(c[i][j]==c[i-1][j-1]+1) 

LCS(i-1,j-1,x,c);

LCS(i-1,j,x,c);

LCS(i,j-1,x,c);

96.} 

运行结果如下:

从运行结果中可以看出,算法LCS回溯算法仅仅打印了其中一条最大公共子序列,如果存在多条公共子序列的情况下。

怎么解决?

对b[i][j]二维数组的取值添加一种可能,等于4,这代表了我们说的这种多支情况,那么回溯的时候可以根据这个信息打印更多可能的选择。

你从(7,6)点开始按b[i][j]的值指示的方向回溯,把所有的路径遍历一遍,如果是能达到起点(1,1)的路径,就是LCS了,有多少条打印多少条。

可是,在回溯路径的时候,如果采用一般的全搜索,会进行了很多无用功。

即重复了很多,且会遍历了一些无效路径,因为这些路径最终不会到达终点(1,1),因此加大算法复杂度和时间消耗。

博文《求所有最大公共子序列的算法实现》给出了一种"

矩行搜索"

的解决办法降低了算法的复杂度。

算法主要是利用两个栈store,print,一个用来储存节点,一个用来打印节点。

栈的实现代码如下(文件Stack.h):

1./** 

2. 

头文件------head 

file 

3. 

*/ 

4. 

5.template 

class 

T>

6.class 

StackNode{ 

7. 

public:

data;

9. 

StackNode 

*next;

10.};

11. 

12.template 

13.class 

Stack{ 

14. 

Stack(void):

top(NULL){} 

bool 

IsEmpty(void) 

const{ 

return 

top==NULL;

void 

Push(const 

data);

Pop(T 

*data);

Peek(T 

*data) 

const;

StackNode<

GetStackNode();

private:

*top;

23.};

25.template 

26.StackNode<

Stack<

:

GetStackNode(){ 

top;

28.} 

30.template 

31.void 

data){ 

*node 

();

node->

data 

next 

top 

node;

36.} 

38.template 

39.bool 

if(IsEmpty()) 

false;

*data 

top->

true;

43.} 

45.template 

46.bool 

*data){ 

48. 

next;

delete(node);

53.} 

所有最长公共子序列问题LCS矩阵搜索代码如下:

1.//3d3-3 

所有最长公共子序列问题LCS 

矩阵搜索 

stack.h"

4.#include 

5.using 

6. 

7.typedef 

**Matrix;

8.const 

9.const 

10. 

11.typedef 

struct 

_Element 

12.{ 

13. 

lcslen;

//当前节点的LCS长度 

row;

//当前节点的行坐标 

col;

//当前节点的列坐标 

16.}Element;

18.void 

20.Element 

CreateElement(int 

nlen, 

row, 

col);

22.Matrix 

GreateMatrix(int 

23.void 

DeleteMatrix(Matrix 

p, 

row);

25.void 

PrintStack(Stack<

Element>

*ps, 

*str, 

len);

26.void 

SearchE(Matrix 

pb, 

curposx, 

curposy, 

&

eposx, 

eposy, 

ntype);

28.void 

*y,Matrix 

pc,Matrix 

pb);

29.void 

LCS(char 

*x, 

Matrix 

pc, 

//矩阵搜索回溯 

3

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1