博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Algorithms] Longest Common Subsequence
阅读量:6693 次
发布时间:2019-06-25

本文共 4223 字,大约阅读时间需要 14 分钟。

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.

1 int longestCommonSubsequence(string s, string t) {2     int m = s.length(), n = t.length();3     vector
> dp(m + 1, vector
(n + 1, 0));4 for (int i = 1; i <= m; i++)5 for (int j = 1; j <= n; j++)6 dp[i][j] = (s[i - 1] == t[j - 1] ? dp[i - 1][j - 1] + 1 : max(dp[i - 1][j], dp[i][j - 1]));7 return dp[m][n];8 }

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.

1 int longestCommonSubsequenceSpaceEfficient(string s, string t) { 2     int m = s.length(), n = t.length(); 3     int maxlen = 0; 4     vector
pre(m, 0); 5 vector
cur(m, 0); 6 pre[0] = (s[0] == t[0]); 7 maxlen = max(maxlen, pre[0]); 8 for (int i = 1; i < m; i++) { 9 if (s[i] == t[0] || pre[i - 1] == 1) pre[i] = 1;10 maxlen = max(maxlen, pre[i]);11 }12 for (int j = 1; j < n; j++) {13 if (s[0] == t[j] || pre[0] == 1) cur[0] = 1;14 maxlen = max(maxlen, cur[0]);15 for (int i = 1; i < m; i++) {16 if (s[i] == t[j]) cur[i] = pre[i - 1] + 1;17 else cur[i] = max(cur[i - 1], pre[i]);18 maxlen = max(maxlen, cur[i]);19 }20 swap(pre, cur);21 fill(cur.begin(), cur.end(), 0);22 }23 return maxlen;24 }

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.

1 int longestCommonSubsequenceSpaceMoreEfficient(string s, string t) { 2     int m = s.length(), n = t.length(); 3     vector
cur(m + 1, 0); 4 for (int j = 1; j <= n; j++) { 5 int pre = 0; 6 for (int i = 1; i <= m; i++) { 7 int temp = cur[i]; 8 cur[i] = (s[i - 1] == t[j - 1] ? pre + 1 : max(cur[i], cur[i - 1])); 9 pre = temp;10 }11 }12 return cur[m];13 }

Now you may try this problem on  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 . The code is as follows.

1 int longestCommonSubsequence(string s, string t) { 2     int m = s.length(), n = t.length(); 3     vector
> dp(m + 1, vector
(n + 1, 0)); 4 for (int i = 1; i <= m; i++) 5 for (int j = 1; j <= n; j++) 6 dp[i][j] = (s[i - 1] == t[j - 1] ? dp[i - 1][j - 1] + 1 : max(dp[i - 1][j], dp[i][j - 1])); 7 int len = dp[m][n]; 8 // Print out the longest common subsequence 9 string lcs(len, ' ');10 for (int i = m, j = n, index = len - 1; i > 0 && j > 0;) {11 if (s[i - 1] == t[j - 1]) {12 lcs[index--] = s[i - 1];13 i--;14 j--;15 }16 else if (dp[i - 1][j] > dp[i][j - 1]) i--;17 else j--;18 }19 printf("%s\n", lcs.c_str());20 return len;21 }

 

转载于:https://www.cnblogs.com/jcliBlogger/p/4574334.html

你可能感兴趣的文章
html中iframe控制父页面刷新
查看>>
每天一个linux命令(50):crontab命令
查看>>
linux命令7--cat命令&nl命令
查看>>
.NET底层开发技术
查看>>
RHEL regiester
查看>>
c/c++中的一些基础知识
查看>>
练习:输出整数每一位,计算算数,9出现次数,输出图案,水仙花数
查看>>
操作系统的发展
查看>>
HEVC码流简单分析
查看>>
搭建蚂蚁笔记(服务器)
查看>>
lnmp
查看>>
Oracle教程之Oralce OMF功能详解(三)--使用Oralce OMF管理控制文件
查看>>
C# extern 修饰符的用法
查看>>
Zabbix修正错误两例(只提供解决思路)
查看>>
Redhat6.X 配置HP3PAR7200存储多路径过程
查看>>
Java基础系列19:使用JXL或者POI生成和解析Excel文件
查看>>
使用xshell打开centos中文显示为乱码
查看>>
达内实习——数据库编程、文件读写数据
查看>>
zabbix 监控percona
查看>>
我的友情链接
查看>>