《算法导论》CLRS算法C++实现(十二)P208 最长公共子序列LCS
来源:互联网 发布:产后护理软件 编辑:程序博客网 时间:2024/04/30 01:39
给定两个序列X和Y,如果Z既是X的一个子序列又是Y的一个子序列,则称序列Z是X和Y的一个公共子序列。
在最长公共子序列问题(LCS)中,给定了两个序列X=<x1,x2,…,xm>和Y=<y1,y2,…,yn>,希望找出X和Y的最大长度的公共子序列。最直观且容易想到的方法是枚举出X的所有子序列,然后逐一检查看其是否为Y的子序列,并随时记录所发现的最长子序列。这种方法的时间复杂度是指数级的,对于较长的序列来说是不实际的。
LCS问题的最优子结构:
若xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的最长公共子序列;
若xm≠yn且zk≠xm ,则Z是Xm-1和Y的最长公共子序列;
若xm≠yn且zk≠yn ,则Z是X和Yn-1的最长公共子序列。
算法:LCS-LENGTH(X, Y)
1 2 m ← length[X] 3 n ← length[Y] 4 for i ← 1 to m 5 do c[i, 0] ← 0 6 for j ← 0 to n 7 do c[0, j] ← 0 8 for i ← 1 to m 9 do for j ← 1 to n10 do if xi = yj11 then c[i, j] ← c[i - 1, j - 1] + 112 b[i, j] ← "↖"13 else if c[i - 1, j] ≥ c[i, j - 1]14 then c[i, j] ← c[i - 1, j]15 b[i, j] ← "↑"16 else c[i, j] ← c[i, j - 1]17 b[i, j] ← ←18 return c and b
C++实现:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 5 using namespace std; 6 7 enum 8 dir {dInit = 0, dLeft, dUp, dUpLeft};//定义方向初始化值dInit,三个方向左dLeft、上dUp、左上dUpLeft 9 10 void LCSPrint(int **LCS_direction, const char* la, const char* lb, int row, int col) 11 { 12 if (la == NULL || lb == NULL) 13 return; 14 15 int lengthA = strlen(la); 16 int lengthB = strlen(lb); 17 18 if (lengthA ==0 || lengthB == 0 || !(row < lengthA && col < lengthB)) 19 return; 20 21 if (LCS_direction[row][col] == dUpLeft) 22 { 23 if (row > 0 && col > 0) 24 LCSPrint(LCS_direction, la, lb, row - 1, col - 1); 25 26 printf("%c", la[row]); 27 } 28 else if (LCS_direction[row][col] == dUp) 29 { 30 if (row > 0) 31 LCSPrint(LCS_direction, la, lb, row - 1, col); 32 } 33 else if(LCS_direction[row][col] == dLeft) 34 { 35 if (col > 0) 36 LCSPrint(LCS_direction, la, lb, row, col - 1); 37 } 38 } 39 40 int 41 LCSLength(const char *la, const char *lb) 42 { 43 if (!la || !lb) 44 return 0; 45 46 int lengthA = strlen(la); 47 int lengthB = strlen(lb); 48 49 if (!lengthA || !lengthB) 50 return 0; 51 52 int i, j; 53 54 //创建并初始化存放长度的二维数组 55 int **LCS_length; 56 LCS_length = (int**)(new int[lengthA]); 57 for (i = 0; i < lengthA; ++i) 58 LCS_length[i] = (int*)new int[lengthB]; 59 60 for (i = 0; i < lengthA; ++i) 61 for (j = 0; j < lengthB; ++j) 62 LCS_length[i][j] = 0; 63 64 //创建并初始化存放方向的二维数组,方向在枚举enum dir中定义 65 int **LCS_direction; 66 LCS_direction = (int**)(new int[lengthA]); 67 for (i = 0; i < lengthA; ++i) 68 LCS_direction[i] = (int*)new int[lengthB]; 69 70 for (i = 0; i < lengthA; ++i) 71 for (j = 0; j < lengthB; ++j) 72 LCS_direction[i][j] = dInit; 73 74 for (i = 0; i < lengthA; ++i) 75 { 76 for (j = 0; j < lengthB; ++j) 77 { 78 if (i == 0 || j == 0) 79 { 80 if (la[i] == lb[j]) 81 { 82 LCS_length[i][j] = 1; 83 LCS_direction[i][j] = dUpLeft; 84 } 85 else 86 { 87 if (i > 0) 88 { 89 //i > 0不是第一行 90 LCS_length[i][j] = LCS_length[i - 1][j]; 91 LCS_direction[i][j] = dUp; 92 } 93 if (j > 0) 94 { 95 //j > 0不是第一列 96 LCS_length[i][j] = LCS_length[i][j - 1]; 97 LCS_direction[i][j] = dLeft; 98 } 99 }100 }101 102 else if (la[i] == lb[j])103 {104 LCS_length[i][j] = LCS_length[i - 1][j - 1] + 1;105 LCS_direction[i][j] = dUpLeft;106 }107 108 else if (LCS_length[i - 1][j] > LCS_length[i][j - 1])109 {110 LCS_length[i][j] = LCS_length[i - 1][j];111 LCS_direction[i][j] = dUp;112 }113 114 else115 {116 LCS_length[i][j] = LCS_length[i][j - 1];117 LCS_direction[i][j] = dLeft;118 }119 }120 }121 LCSPrint(LCS_direction, la, lb, lengthA - 1, lengthB - 1);122 cout << endl;123 return LCS_length[lengthA - 1][lengthB - 1];124 }125 126 int main()127 {128 const char* la = "ABCBDAB";129 const char* lb = "BDCABA";130 int length = LCSLength(la, lb);131 cout << "最长子序列长度为:" << length << endl;132 return 0;133 }
Python实现:
1 def LCS(la, lb): 2 if la == "" or lb == "": 3 return 4 lengthA = len(la) 5 lengthB = len(lb) 6 lcs = [[0] for i in range(0, lengthA + 1)] 7 lcs[0] = [0 for j in range(0, lengthB + 1)] 8 for i in range(lengthA): 9 for j in range(lengthB):10 lcs[i + 1].append(lcs[i][j] + 1 if la[i] == lb[j] else max(lcs[i][j + 1], lcs[i + 1][j]))11 i = lengthA - 112 j = lengthB - 113 lcsstr = ""14 while True:15 if i == -1 or j == -1:16 break17 if la[i] == lb[j]:18 lcsstr = "%s%s" % (la[i], lcsstr)19 i = i - 120 j = j - 121 else:22 if lcs[i][j + 1] > lcs[i + 1][j]:23 i = i - 124 else:25 j = j - 126 print lcsstr27 28 LCS("ABCBDAB", "BDCABA")
- 《算法导论》CLRS算法C++实现(十二)P208 最长公共子序列LCS
- 算法导论(LCS最长公共子序列)
- 算法导论学习笔记(十二):动态规划(二):最长公共子序列(LCS)
- 算法导论-----最长公共子序列LCS(动态规划)
- 最长公共子序列(LCS) (动态规划算法实现)算法导论p211
- Java实现算法导论中最长公共子序列(LCS)动态规划法
- 最长公共子序列算法(LCS)
- LCS算法(最长公共子序列)
- 最长公共子序列(LCS)算法
- 算法学习 - 最长公共子序列(LCS)C++实现
- LCS算法(动态规划实现最长公共子序列)c语言实现
- 《算法导论》实验二:最长公共子序列(LCS)算法
- 算法导论——动态规划之最长公共子序列(LCS)和最长回文子序列(LPS)
- 算法导论第15章 最长公共子序列问题(LCS)
- 算法导论--------------LCS问题(最长公共子系列)
- 编程算法 - 最长公共子序列(LCS) 代码(C)
- 《算法导论》动态规划—最长公共子序列(不连续)--c语言实现
- 动态规划实现最长公共子序列(LCS)算法
- kernel/power/wakelock.c 中为什么要使用工作队列线程?
- 《算法导论》CLRS算法C++实现(九)P109 选择数组中第i小(大)的数 顺序统计量
- 《算法导论》CLRS算法C++实现(十)P151 二叉查找树
- 《算法导论》CLRS算法C++实现 索引
- 《算法导论》CLRS算法C++实现(十一)P163 红黑树
- 《算法导论》CLRS算法C++实现(十二)P208 最长公共子序列LCS
- Linux API函数总结
- Nginx简介与安装
- Google面试题:在柱状图中找最大的矩形
- 为什么应该用模块取代C/C++中的头文件?
- LeetCode: Flatten Binary Tree to Linked List
- Win8简单几何图形的绘制
- android中以项目依赖的方式引用其他项目
- 在Asp.net中,(Entityframework,Linq的写法中) .ToList().Take(10)与.Take(10).ToList() 的区别