博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Algorithms] Longest Common Subsequence
阅读量:6706 次
发布时间: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

你可能感兴趣的文章
hdu 5400 Arithmetic Sequence(模拟)
查看>>
求职(2015南京站获得百度、美的集团、趋势科技、华为offer)
查看>>
压测 apache ab 初探
查看>>
设计数据结构O1 insert delete和getRandom
查看>>
视图(View)与部分视图(Partial View)之间数据传递
查看>>
漫谈程序猿系列:群星闪耀的黄金时代
查看>>
使用Spring Session做分布式会话管理
查看>>
mongodb的NUMA问题
查看>>
js进阶 12-14 jquery的事件触发函数是哪两个
查看>>
网速4M等于多少KB/S,等于多少kbps
查看>>
MySQL MERGE存储引擎 简介
查看>>
atitit。自己定义uml MOF EMF体系eclipse emf 教程o7t
查看>>
atitit.taskService 任务管理器的设计 v1
查看>>
编写jquery插件的分享
查看>>
机器学习 —— 概率图模型(学习:对数线性模型)
查看>>
2016百度编程题:蘑菇阵
查看>>
解决教学问题新感悟
查看>>
nyoj 37 回文字符串
查看>>
Lintcode--006(交叉字符串)
查看>>
ASP.NET Core 1.0基础之依赖注入
查看>>