[Algorithms] Longest Common Subsequence
The Longest Common Subsequence (LCS) problem is as follows:
Given two sequences s and t, find the length of the longest sequence r, which is a subsequence of both s and t.
Do you know the difference between substring and subequence? Well, substring is a contiguous series of characters while subsequence is not necessarily. For example, "abc" is a both a substring and a subseqeunce of "abcde" while "ade" is only a subsequence.
This problem is a classic application of Dynamic Programming. Let's define the sub-problem (state) P[i][j] to be the length of the longest subsequence ends at i of s and j of t. Then the state equations are
- P[i][j] = max(P[i][j - 1], P[i - 1][j]) if s[i] != t[j];
- P[i][j] = P[i - 1][j - 1] + 1 if s[i] == t[j].
This algorithm gives the length of the longest common subsequence. The code is as follows.
int longestCommonSubsequence(string s, string t) {
int m = s.length(), n = t.length();
vector<vector<int> > dp(m + , vector<int> (n + , ));
for (int i = ; i <= m; i++)
for (int j = ; j <= n; j++)
dp[i][j] = (s[i - ] == t[j - ] ? dp[i - ][j - ] + : max(dp[i - ][j], dp[i][j - ]));
return dp[m][n];
}
Well, this code has both time and space complexity of O(m*n). Note that when we update dp[i][j], we only need dp[i - 1][j - 1], dp[i - 1][j] and dp[i][j - 1]. So we simply need to maintain two columns for them. The code is as follows.
int longestCommonSubsequenceSpaceEfficient(string s, string t) {
int m = s.length(), n = t.length();
int maxlen = ;
vector<int> pre(m, );
vector<int> cur(m, );
pre[] = (s[] == t[]);
maxlen = max(maxlen, pre[]);
for (int i = ; i < m; i++) {
if (s[i] == t[] || pre[i - ] == ) pre[i] = ;
maxlen = max(maxlen, pre[i]);
}
for (int j = ; j < n; j++) {
if (s[] == t[j] || pre[] == ) cur[] = ;
maxlen = max(maxlen, cur[]);
for (int i = ; i < m; i++) {
if (s[i] == t[j]) cur[i] = pre[i - ] + ;
else cur[i] = max(cur[i - ], pre[i]);
maxlen = max(maxlen, cur[i]);
}
swap(pre, cur);
fill(cur.begin(), cur.end(), );
}
return maxlen;
}
Well, keeping two columns is just for retriving pre[i - 1], we can maintain a single variable for it and keep only one column. The code becomes more efficient and also shorter. However, you may need to run some examples to see how it achieves the things done by the two-column version.
int longestCommonSubsequenceSpaceMoreEfficient(string s, string t) {
int m = s.length(), n = t.length();
vector<int> cur(m + , );
for (int j = ; j <= n; j++) {
int pre = ;
for (int i = ; i <= m; i++) {
int temp = cur[i];
cur[i] = (s[i - ] == t[j - ] ? pre + : max(cur[i], cur[i - ]));
pre = temp;
}
}
return cur[m];
}
Now you may try this problem on UVa Online Judge and get Accepted:)
Of course, the above code only returns the length of the longest common subsequence. If you want to print the lcs itself, you need to visit the 2-d table from bottom-right to top-left. The detailed algorithm is clearly explained here. The code is as follows.
int longestCommonSubsequence(string s, string t) {
int m = s.length(), n = t.length();
vector<vector<int> > dp(m + , vector<int> (n + , ));
for (int i = ; i <= m; i++)
for (int j = ; j <= n; j++)
dp[i][j] = (s[i - ] == t[j - ] ? dp[i - ][j - ] + : max(dp[i - ][j], dp[i][j - ]));
int len = dp[m][n];
// Print out the longest common subsequence
string lcs(len, ' ');
for (int i = m, j = n, index = len - ; i > && j > ;) {
if (s[i - ] == t[j - ]) {
lcs[index--] = s[i - ];
i--;
j--;
}
else if (dp[i - ][j] > dp[i][j - ]) i--;
else j--;
}
printf("%s\n", lcs.c_str());
return len;
}
[Algorithms] Longest Common Subsequence的更多相关文章
- [Algorithms] Using Dynamic Programming to Solve longest common subsequence problem
Let's say we have two strings: str1 = 'ACDEB' str2 = 'AEBC' We need to find the longest common subse ...
- 动态规划求最长公共子序列(Longest Common Subsequence, LCS)
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- LintCode Longest Common Subsequence
原题链接在这里:http://www.lintcode.com/en/problem/longest-common-subsequence/ 题目: Given two strings, find t ...
- [UCSD白板题] Longest Common Subsequence of Three Sequences
Problem Introduction In this problem, your goal is to compute the length of a longest common subsequ ...
- LCS(Longest Common Subsequence 最长公共子序列)
最长公共子序列 英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...
- Longest Common Subsequence
Given two strings, find the longest common subsequence (LCS). Your code should return the length of ...
- Longest Common Subsequence & Substring & prefix
Given two strings, find the longest common subsequence (LCS). Your code should return the length of ...
- Dynamic Programming | Set 4 (Longest Common Subsequence)
首先来看什么是最长公共子序列:给定两个序列,找到两个序列中均存在的最长公共子序列的长度.子序列需要以相关的顺序呈现,但不必连续.例如,"abc", "abg", ...
- Lintcode:Longest Common Subsequence 解题报告
Longest Common Subsequence 原题链接:http://lintcode.com/zh-cn/problem/longest-common-subsequence/ Given ...
随机推荐
- Android studio使用心得(二)— 打包签名apk发布
1.—–Android Studio菜单 Build->Generate Signed APK 2.——Create new.. 3.——-跟eclipse里面一样,添加keystore 信 ...
- python3 logging 日志记录模块
#coding:utf-8 import logginglogging.basicConfig(filename='log1.log', format='%(asctime)s -%(name)s-% ...
- Centos下源码安装git
1.centos下git版本太久了,才1.8几,而官方更新的还是很活跃的,于是我就想源码安装一个新版本. 2.首先到: https://github.com/git/git/releases 下载最新 ...
- [svc][op]如何查看当前Ubuntu系统的版本
如何查看当前Ubuntu系统的版本 说来也惭愧,用Ubuntu差不多快1个月了,双系统是让朋友安的,只知道自己使用的是什么12版本的,具体怎么看还不知道,下面写一下查看当前Linux系统的版本的方法 ...
- std::thread “terminate called without an active exception”
最近在使用std::thread的时候,遇到这样一个问题: std::thread t(func); 如果不使用调用t.join()就会遇到 "terminate called whitho ...
- 在控制台快速定位js函数
最近在搞教务处的模拟登录,教务处用js加密密码和账号,为了构造能用的post数据,需要快速的找到对应的js代码.但是,那么多js代码,手动找会找到死的. 恰好学习了两个快速定位的方法:console ...
- vi/vim 光标移动命令
vi/vim 光标移动命令 移动光标上:k nk:向上移动n行 9999k或gg可以移到第一行 G移到最后一行下:j nj:向下移动n行左:h nh:向左移动n列右:l nl:向右移动n列 w:光标以 ...
- PHP——菜单及内容轮换(Jquery)
效果: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3. ...
- zend studio 10.6.2 字体大小 设置
如果汉化的:窗体-->常规-->外观-->颜色和字体-->基本-->文字字体 点击编辑 如果未汉化:Window->Preferences->General ...
- adb 安装apk到指定手机 登录shell
电脑链接多个设备时,给指定的设备安装apk, 1. 先查看手机的编码 adb devices 2. adb -s 手机编码 install xxx.apk 如果是无线链接调试状态,adb device ...