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

  1. P[i][j] = max(P[i][j - 1], P[i - 1][j]) if s[i] != t[j];
  2. 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的更多相关文章

  1. [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 ...

  2. 动态规划求最长公共子序列(Longest Common Subsequence, LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  3. LintCode Longest Common Subsequence

    原题链接在这里:http://www.lintcode.com/en/problem/longest-common-subsequence/ 题目: Given two strings, find t ...

  4. [UCSD白板题] Longest Common Subsequence of Three Sequences

    Problem Introduction In this problem, your goal is to compute the length of a longest common subsequ ...

  5. LCS(Longest Common Subsequence 最长公共子序列)

    最长公共子序列 英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...

  6. Longest Common Subsequence

    Given two strings, find the longest common subsequence (LCS). Your code should return the length of  ...

  7. Longest Common Subsequence & Substring & prefix

    Given two strings, find the longest common subsequence (LCS). Your code should return the length of  ...

  8. Dynamic Programming | Set 4 (Longest Common Subsequence)

    首先来看什么是最长公共子序列:给定两个序列,找到两个序列中均存在的最长公共子序列的长度.子序列需要以相关的顺序呈现,但不必连续.例如,"abc", "abg", ...

  9. Lintcode:Longest Common Subsequence 解题报告

    Longest Common Subsequence 原题链接:http://lintcode.com/zh-cn/problem/longest-common-subsequence/ Given ...

随机推荐

  1. android的五大布局(layout)

    Android的界面是有布局和组件协同完成的,布局好比是建筑里的框架,而组件则相当于建 筑里的砖瓦.组件按照布局的要求依次排列,就组成了用户所看见的界面.Android的五大布局分别是LinearLa ...

  2. 【转】H.264(H264)视频文件的制作

    转自:http://blog.csdn.net/caoshangpa/article/details/51166109 一.准备工作 1.下载并安装优酷客户端 2.下载ffmpeg可执行文件,解压可用 ...

  3. CentOS搭建nginx与nginx-rtmp-module搭建流媒体服务器

    文章地址:http://blog.csdn.net/zph1234/article/details/52846223 本次搭建流媒体使用的环境是centos 7.0+nginx:让我们一起开始奇妙的流 ...

  4. Android之常用功能代码

    透明导航栏 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { getWindow().addFlags(WindowManage ...

  5. Freeswitch中文用户手册(第四章 SIP)----2

    通过 B2BUA 呼叫 在真实世界中,bob 和 alice 肯定要经常改变位置,那么它们的 SIP 地址也会相应改变,并且,如果他们之中有一个或两个处于 NAT 的网络中时,直接通信就更困难了.所以 ...

  6. 点滴积累【other】---win2003 service pack2 IIS 无法复制CONVLOG.EXE CONVLOG.EX_(转载)

    在安装的时候出现一个错误提示“安装程序无法复制文件CONVLOG.EX_”,上网找了下资料,说是在运行-中输入”esentutl /p %windir%/security/database/seced ...

  7. 使用jquery dialog

    网页开发中,弹窗还是很有必要的.本人比较喜欢jquery ui的dialog. 但是jquery dialog中也有一些略显不方便的,如:没有z-index的参数设置,脚部的按钮样式没办法自定义…… ...

  8. Linq之ToList

    今晚遇到一个很奇怪的事情,我已经把所有数据拿出来了,然后在后台用C#代码根据业务对数据进行处理,大抵都是用linq进行一些where.any.select的处理,中间还夹杂着两三个foreach,结果 ...

  9. 点击按钮,实现两个td值互换

    <body> <table id="table1"> <tr> <td>第一个单元格</td> <td>第二 ...

  10. [转]C++11 标准新特性:Defaulted 和 Deleted 函数

    http://www.ibm.com/developerworks/cn/aix/library/1212_lufang_c11new/