动态规划 -- 最长公共子序列
来源:互联网 发布:网络主播排行榜2017 编辑:程序博客网 时间:2024/06/06 09:29
动态规划之最长公共子序列
参考资料
1 算法导论
2 v_JULY_v
3 何海涛
最长公共子序列(Longest Common Subsequence)
给定两个序列 X 和 Y ,称序列 Z 是 X 和 Y 的公共子序列,如果 Z 即是 X 的一个子序列又是 Y 的一个子序列, 该公共子序列不要求是连续的,只是要求Z的元素在X和Y中是以相同的顺序出现。例如,如果 X = { A , B , C , B , D , A , B } ,Y = { B , D , C , A , B , A } ,则序列 { B , C , B , A } 即为 X 和 Y 的一个公共子序列。序列 { B , C, A } 不是 X 和 Y 的一个最长公共子序列,因为长度只是3 ,不是最长的。
递归解
在找X= ( x1,⋯,xm )和 Y = ( y1,⋯,yn ) 的一个 LCS时,需要检查一个或两个子问题。如果 xm = yn,必须找出 xm-1 和 yn-1的一个LCS。将 xm = yn 添加到这个 LCS上,可以产生 X 和 Y 的一个 LCS 。如果 xm != yn ,就必须解决两个子问题,找出xm-1和Y 的一个LCS,以及找出 X 和 yn-1 的一个LCS 。这两个LCS中,较长的就是 X和 Y 的一个 LCS 。
所以 LCS的递归式如下:
计算 LCS 的长度
LCS-LENGTH ( X , Y) m ← length[ X ] n ← length[ Y ] for i ← 1 to mdo c[i,0] ← 0 for j ← 0 to n do c[0,j] ← 0 for i ← 1 to mdo for j ← 1 to ndo if xi = yjthen c[i,j] ← c[i-1,j-1] +1 b[i,j] ← “ \”else if c[i-1,j] > c[i,j-1] then c[i,j] ← c[i-1,j] b[i,j] ← " |"else c[i,j] ← c[i,j-1]b[i,j] ← “---” return c and b
构造一个LCS
PRINT-LCS(b,X,i,j) if i=0 or j=0 then return; if b[i,j]="\" then LCS(b,X,i-1,j-1); print(x[i]); else if b[i,j]="|" then LCS(b,X,i-1,j) else LCS(b,X,i,j-1);
代码实现
#include "string.h"// directions of LCS generationenum decreaseDir {kInit = 0, kLeft, kUp, kLeftUp};/////////////////////////////////////////////////////////////////////////////// Get the length of two strings' LCSs, and print one of the LCSs// Input: pStr1 - the first string// pStr2 - the second string// Output: the length of two strings' LCSs/////////////////////////////////////////////////////////////////////////////int LCS(char* pStr1, char* pStr2){ if(!pStr1 || !pStr2) return 0; size_t length1 = strlen(pStr1); size_t length2 = strlen(pStr2); if(!length1 || !length2) return 0; size_t i, j; // initiate the length matrix int **LCS_length; LCS_length = (int**)(new int[length1]); for(i = 0; i < length1; ++ i) LCS_length[i] = (int*)new int[length2]; for(i = 0; i < length1; ++ i) for(j = 0; j < length2; ++ j) LCS_length[i][j] = 0; // initiate the direction matrix int **LCS_direction; LCS_direction = (int**)(new int[length1]); for( i = 0; i < length1; ++ i) LCS_direction[i] = (int*)new int[length2]; for(i = 0; i < length1; ++ i) for(j = 0; j < length2; ++ j) LCS_direction[i][j] = kInit; for(i = 0; i < length1; ++ i) { for(j = 0; j < length2; ++ j) { if(i == 0 || j == 0) { if(pStr1[i] == pStr2[j]) { LCS_length[i][j] = 1; LCS_direction[i][j] = kLeftUp; } else LCS_length[i][j] = 0; } // a char of LCS is found, // it comes from the left up entry in the direction matrix else if(pStr1[i] == pStr2[j]) { LCS_length[i][j] = LCS_length[i - 1][j - 1] + 1; LCS_direction[i][j] = kLeftUp; } // it comes from the up entry in the direction matrix else if(LCS_length[i - 1][j] > LCS_length[i][j - 1]) { LCS_length[i][j] = LCS_length[i - 1][j]; LCS_direction[i][j] = kUp; } // it comes from the left entry in the direction matrix else { LCS_length[i][j] = LCS_length[i][j - 1]; LCS_direction[i][j] = kLeft; } } } LCS_Print(LCS_direction, pStr1, pStr2, length1 - 1, length2 - 1); for(i = 0; i < length1; i++) { delete [] LCS_length[i]; delete [] LCS_direction[i]; } return LCS_length[length1 - 1][length2 - 1];}/////////////////////////////////////////////////////////////////////////////// Print a LCS for two strings// Input: LCS_direction - a 2d matrix which records the direction of // LCS generation// pStr1 - the first string// pStr2 - the second string// row - the row index in the matrix LCS_direction// col - the column index in the matrix LCS_direction/////////////////////////////////////////////////////////////////////////////void LCS_Print(int **LCS_direction, char* pStr1, char* pStr2, size_t row, size_t col){ if(pStr1 == NULL || pStr2 == NULL) return; size_t length1 = strlen(pStr1); size_t length2 = strlen(pStr2); if(length1 == 0 || length2 == 0 || !(row < length1 && col < length2)) return; // kLeftUp implies a char in the LCS is found if(LCS_direction[row][col] == kLeftUp) { if(row > 0 && col > 0) LCS_Print(LCS_direction, pStr1, pStr2, row - 1, col - 1); // print the char printf("%c", pStr1[row]); } else if(LCS_direction[row][col] == kLeft) { // move to the left entry in the direction matrix if(col > 0) LCS_Print(LCS_direction, pStr1, pStr2, row, col - 1); } else if(LCS_direction[row][col] == kUp) { // move to the up entry in the direction matrix if(row > 0) LCS_Print(LCS_direction, pStr1, pStr2, row - 1, col); }}
- 最长公共子序列&&最长公共子串---[动态规划]
- 动态规划-最长公共子序列、最长公共子串
- 动态规划之最长公共子序列
- 动态规划 ------- 最长公共子序列
- 动态规划实现最长公共子序列
- 【动态规划】最长公共子序列LCS
- 动态规划--最长公共子序列
- 动态规划:最长公共子序列
- 动态规划解决最长公共子序列
- 最长公共子序列-动态规划DP
- 动态规划--最长公共子序列
- 最长公共子序列(动态规划)
- 动态规划解决最长公共子序列
- 最长公共子序列(动态规划)
- 动态规划 最长公共子序列
- 动态规划 - 最长公共子序列
- 动态规划之最长公共子序列
- 最长公共子序列 [动态规划]
- ::前面没有类名 代表了全局作用域
- Android的webview加载本地html、本apk内html和远程URL
- 东软---实习报告
- c# 调用 pdf2swf.exe
- jar(包)
- 动态规划 -- 最长公共子序列
- POJ1157 LITTLE SHOP OF FLOWERS
- Linux运维
- 如何预置APK
- gevent pywsgi overflow
- java获取当前时间最接近的刻度时间(00,15,30,45)
- 笔试面试题之递归
- 回文字符串
- C语言打印自己