算法实践--最长公共子序列(Longest Common Subsquence)
什么是最长公共子序列
X=ACCG
Y=CCAGCA
长度为1的公共子序列: {A} {C} {G}
长度为2的公共子序列:{AC} {CC} {CG} {AG}
长度为3的公共子序列:{ACG}
长度为4的公共子序列
最长公共子序列即为 {ACG}
问题:长度为N和M的两个序列如何求他们的最长公共子序列?
X = ACCGGGTTACCGTTTAAAACCCGGGTAACCT
Y = CCAGGACCAGGGACCGTTTACCAGCCTTAAACCA
简单算法
for (int i=N; i>0; --i) {
找到X所有长度为i的子序列;
找到Y所有长度为i的子序列;
如果存在公共子序列则终止
}
复杂度O(2^N)
动态规划算法
定义C[i][j]为序列X[i..i]和Y[1..j]的最长子序列的长度
C[i][0]和C[0][j]==0
递推公式
C[i][j]=C[i-1][j-1]+1, X[i]==Y[j]
C[i][j]=MAX(C[i-1][j], C[i][j-1]), X[i]!=Y[j]
C++实现
template<typename T>
void prtM(vector< vector<T> >& arr, string msg = "") {
cout << msg << " " << endl;
for (auto i: arr) {
for (auto j: i) {
cout << j << " ";
}
cout << endl;
}
cout << endl;
} template <typename T>
void prt(vector<T>& arr, string msg = "") {
cout << msg << " ";
for (auto i: arr) {
cout << i << " ";
}
cout << endl;
} void prt_LCS(vector< vector<char> >& S, string& X, int i, int j) { // 递归调用
//cout << "i=" << i << " j=" << j << " " << S[i][j] << endl;
if (i== || j == )
return;
if ('s' == S[i][j]) {
prt_LCS(S, X, i-, j-);
cout << X[i];
} else if ('j' == S[i][j]) {
prt_LCS(S, X, i, j-);
} else {
prt_LCS(S, X, i-, j);
}
} void calc_LCS(string& X, string& Y) {
cout << "X: " << X << endl;
cout << "Y: " << Y << endl; vector< vector<int> > C; // 序列X[0..i] and Y[0..j]的公共子序列的长度
vector< vector<char> > S; //最长公共子串的位置
for (int i=; i<X.size(); i++) {
C.push_back( vector<int>(Y.size()) );
S.push_back( vector<char>(Y.size()) );
} for (int i=; i<X.size(); i++)
C[i][] = ;
for (int j=; j<Y.size(); j++)
C[][j] = ; for (int i=; i<X.size(); i++)
for (int j=; j<Y.size(); j++) {
if (X[i] == Y[j]) {
C[i][j] = C[i-][j-] + ;
S[i][j] = 's'; // 相同,可以打印
} else if ( C[i][j-] > C[i-][j] ) {
C[i][j] = C[i][j-];
S[i][j] = 'j'; //Y的最后一个可以去掉,不影响LCS
} else {
C[i][j] = C[i-][j] ;
S[i][j] = 'i'; //X的最后一个可以去掉,不影响LCS
}
} prtM(C);
prtM(S);
prt_LCS(S, X, X.size()-, Y.size()-);
cout<< endl;
} int main() { string S1 = " ACCGGGTTAC"; // 为了方便表示,忽略第一个字符
string S2 = " AGGACCA"; calc_LCS(S1, S2); return ;
}
算法实践--最长公共子序列(Longest Common Subsquence)的更多相关文章
- 算法实践--最长递增子序列(Longest Increasing Subsquence)
什么是最长递增子序列(Longest Increasing Subsquence) 对于一个序列{3, 2, 6, 4, 5, 1},它包含很多递增子序列{3, 6}, {2,6}, {2, 4, 5 ...
- 最长公共子序列(Longest common subsequence)
问题描述: 给定两个序列 X=<x1, x2, ..., xm>, Y<y1, y2, ..., yn>,求X和Y长度最长的公共子序列.(子序列中的字符不要求连续) 这道题可以 ...
- 算法练习——最长公共子序列的问题(LCS)
问题描述: 对于两个序列X和Y的公共子序列中,长度最长的那个,定义为X和Y的最长公共子序列.X Y 各自字符串有顺序,但是不一定需要相邻. 最长公共子串(Longest Common Subst ...
- 最长公共子串(Longest common substring)
问题描述: 给定两个序列 X=<x1, x2, ..., xm>, Y<y1, y2, ..., yn>,求X和Y长度最长的公共子串.(子串中的字符要求连续) 这道题和最长公共 ...
- Java实现 蓝桥杯VIP 算法提高 最长公共子序列
算法提高 最长公共子序列 时间限制:1.0s 内存限制:256.0MB 问题描述 给定两个字符串,寻找这两个字串之间的最长公共子序列. 输入格式 输入两行,分别包含一个字符串,仅含有小写字母. 输出格 ...
- 【算法】最长公共子序列(nlogn)
转载注明出处:http://blog.csdn.net/wdq347/article/details/9001005 (修正了一些错误,并自己重写了代码) 最长公共子序列(LCS)最常见的算法是时间复 ...
- ACM/ICPC 之 最长公共子序列计数及其回溯算法(51Nod-1006(最长公共子序列))
这道题被51Nod定为基础题(这要求有点高啊),我感觉应该可以算作一级或者二级题目,主要原因不是动态规划的状态转移方程的问题,而是需要理解最后的回溯算法. 题目大意:找到两个字符串中最长的子序列,子序 ...
- 利用后缀数组(suffix array)求最长公共子串(longest common substring)
摘要:本文讨论了最长公共子串的的相关算法的时间复杂度,然后在后缀数组的基础上提出了一个时间复杂度为o(n^2*logn),空间复杂度为o(n)的算法.该算法虽然不及动态规划和后缀树算法的复杂度低,但其 ...
- [Swift]LeetCode14. 最长公共前缀 | Longest Common Prefix
Write a function to find the longest common prefix string amongst an array of strings. If there is n ...
随机推荐
- 1021. Remove Outermost Parentheses删除最外层的括号
网址:https://leetcode.com/problems/remove-outermost-parentheses/ 使用栈的思想,选择合适的判断时机 class Solution { pub ...
- 多线程thread的使用
1.thread是多线程,凡是thread的子类都是一个线程. 2.thread必须调用start方法进开启线程,不能直接调用Runnable中的run方法,因为直接调用run方法没有创建新的线程,就 ...
- 批量注册当前文件夹中的dll和ocx
新建文件:RegisterDllAndOcx.bat如下 @echo offecho hello,girl~~for %%i in (*.dll *.ocx) do (echo %% register ...
- html 入门 "地表最强"干货 你值得拥有
# 入门 ## 一.前端三剑客 #### html ```完成页面架构的搭建文件: .html``` #### css ```完成页面样式布局(装修)文件: .css``` #### js ```完成 ...
- UVa 11100 - The Trip, 2007 难度: 0
题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...
- Python基础综合练习
from turtle import * def draw(x): begin_fill() for i in range(5): forward(x) right(144) end_fill() d ...
- 【转载】Oracle 中count(1) 、count(*) 和count(列名) 函数的区别
1)count(1)与count(*)比较: 1.如果你的数据表没有主键,那么count(1)比count(*)快2.如果有主键的话,那主键(联合主键)作为count的条件也比count(*)要快3. ...
- 二十三. Python基础(23)--经典类和新式类
二十三. Python基础(23)--经典类和新式类 ●知识框架 ●接口类&抽象类的实现 # 接口类&抽象类的实现 #①抛出异常法 class Parent(object): ...
- 阶段01Java基础day21IO流02
21.01_IO流(字符流FileReader) 1.字符流是什么 字符流是可以直接读写字符的IO流 字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要写出字符, 需要把字符转为字节再写 ...
- Codeforces Round #324 (Div. 2) (哥德巴赫猜想)
题目:http://codeforces.com/problemset/problem/584/D 思路: 关于偶数的哥德巴赫猜想:任一大于2的偶数都可写成两个素数之和. 关于奇数的哥德巴赫猜想:任一 ...