求最长公共子序列-DP问题

Longest common subsequence problem

The longest common subsequence (LCS) problem is the problem of finding the longest subsequence common to all sequences in a set of sequences (often just two sequences). It differs from the longest common substring problem: unlike substrings, subsequences are not required to occupy consecutive positions within the original sequences.

Example

  • LCS for input Sequences ABCDGH and AEDFHR is ADH of length 3.
  • LCS for input Sequences AGGTAB and GXTXAYB is GTAB of length 4

以s1={1,3,4,5,6,7,7,8},s2={3,5,7,4,8,6,7,8,2}为例。

1.构建二维矩阵A[n+1][n+1] s1为列,s2为行

(1)A[0][any]=0,A[any][0]=0

(2)if(s1[columnIndex-1]==s2[rowIndex-1])则A[rowIndex][columnIndex]=A[rowIndex-1][columnIndex-1]+1;

else  A[rowIndex][columnIndex]=max(A[rowIndex][columnIndex-1],A[rowIndex-1][columnIndex])

(3)由A[8][9]可知最大子序列长度。

图如下:

2.针对构建的二维矩阵求最长子序列

(1)当columnIndex>0或者rowIndex>0时。

(2)如果s1[columnIndex-1]==s2[rowIndex-1]则longestSequence.unshift(s1[columnIndex-1]).rowIndex--;columnIndex--.

(3)如果不等,

则1.如果A[rowIndex][columnIndex]==A[rowIndex][columnIndex-1];columnIndex--;//向左

      2.否则 rowIndex--;

代码如下:

/**
 * @param {string[]} set1
 * @param {string[]} set2
 * @return {string[]}
 */
export default function longestCommonSubsequence(set1, set2) {
  // Init LCS matrix.
  const lcsMatrix = Array(set2.length + 1).fill(null).map(() => Array(set1.length + 1).fill(null));

  // Fill first row with zeros.
  for (let columnIndex = 0; columnIndex <= set1.length; columnIndex += 1) {
    lcsMatrix[0][columnIndex] = 0;
  }

  // Fill first column with zeros.
  for (let rowIndex = 0; rowIndex <= set2.length; rowIndex += 1) {
    lcsMatrix[rowIndex][0] = 0;
  }

  // Fill rest of the column that correspond to each of two strings.
  for (let rowIndex = 1; rowIndex <= set2.length; rowIndex += 1) {
    for (let columnIndex = 1; columnIndex <= set1.length; columnIndex += 1) {
      if (set1[columnIndex - 1] === set2[rowIndex - 1]) {
        lcsMatrix[rowIndex][columnIndex] = lcsMatrix[rowIndex - 1][columnIndex - 1] + 1;
      } else {
        lcsMatrix[rowIndex][columnIndex] = Math.max(
          lcsMatrix[rowIndex - 1][columnIndex],
          lcsMatrix[rowIndex][columnIndex - 1],
        );
      }
    }
  }

  // Calculate LCS based on LCS matrix.
  if (!lcsMatrix[set2.length][set1.length]) {
    // If the length of largest common string is zero then return empty string.
    return [‘‘];
  }

  const longestSequence = [];
  let columnIndex = set1.length;
  let rowIndex = set2.length;

  while (columnIndex > 0 || rowIndex > 0) {
    if (set1[columnIndex - 1] === set2[rowIndex - 1]) {
      // Move by diagonal left-top.
      longestSequence.unshift(set1[columnIndex - 1]);
      columnIndex -= 1;
      rowIndex -= 1;
    } else if (lcsMatrix[rowIndex][columnIndex] === lcsMatrix[rowIndex][columnIndex - 1]) {
      // Move left.
      columnIndex -= 1;
    } else {
      // Move up.
      rowIndex -= 1;
    }
  }

  return longestSequence;
}


原文地址:https://www.cnblogs.com/Archer-Fang/p/10551181.html

时间: 2024-10-10 16:30:38

求最长公共子序列-DP问题的相关文章

(hdu step 3.2.2)Common Subsequence(简单dp:求最长公共子序列的长度)

在写题解之前给自己打一下广告哈~..抱歉了,希望大家多多支持我在CSDN的视频课程,地址如下: http://edu.csdn.net/course/detail/209 题目: Common Subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 976 Accepted Submission(s): 538   Probl

HDU 1243 反恐训练营 (动态规划求最长公共子序列)

反恐训练营 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3040    Accepted Submission(s): 693 Problem Description 当今国际反恐形势很严峻,特别是美国"9.11事件"以后,国际恐怖势力更是有恃无恐,制造了多起骇人听闻的恐怖事件.基于此,各国都十分担心恐怖势力会对本国社会造

[algorithm]求最长公共子序列问题

最直白方法:时间复杂度是O(n3), 空间复杂度是常数 reference:http://blog.csdn.net/monkeyandy/article/details/7957263 /** ** [email protected] ** http://blog.csdn.net/MonkeyAndy **/ 首先介绍动态规划方法的相关知识 动态规划方法的基本思想: 分成若干个子问题,先求解子问题,然后根据子问题的解求得原问题的解.经分解得到的子问题往往不是互相独立的.可重复利用! 其核心思

LCS求最长公共子序列(DP)

动态规划并不是一种算法,而是一种解决问题的思路.典型的动态规划问题,如最长公共子序列(LCS),最长单调子序列(LIS)等. 动态规划分为四个步骤: 1.判断问题是否具有最优子结构 这里以LCS为例,X={x1,x2,...,xi}:Y={y1,y2,...,yj}.最长公共子序列Z={z1,z2,...,zk}: ①如果xi=yj,那么zk=xi=yj,且Zk-1是序列Xi-1和Yj-1的LCS: ②如果xi≠yj,那么zk≠xi:且Zk是序列Xi-1和Yj的LCS: ③如果xi≠yj,那么z

hdu 1159 common sequence (最长公共子序列 dp)

http://acm.hdu.edu.cn/showproblem.php?pid=1159 题意 : 给出两个字符串 求出最长公共子序列 思路: if(str1[i]==str2[j]) { dp[i][j]=max(dp[i-1][j-1]+1,max(dp[i-1][j],dp[i][j-1])); } else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); #include<cstdio> #include<cstring> #include&l

lcs(最长公共子序列),dp

lcs(最长公共子序列) 求两个序列的lcs的长度,子序列可不连续 dp[i][j]=dp[i-1][j-1]+1(a[i]==b[i]) dp[i][j]=max(dp[i-1][j],dp[i][j-1])(a[i]!=b[i]) memset(dp,0,sizeof(dp)); for(int i=1;i<=n1;i++){ for(int j=1;j<=n2;j++){ if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(

UVA 10635--Prince and Princess+nlgn求最长公共子序列

题目链接:点击进入 刚看到这题目还以为又碰到水题了,结果写了个O(n^2)的代码交上去超时了,才发现n有250*250那么大.后面在网上找到了一个nlgn求最长上升子序列的方法,才过了.这个nlgn算法的主要思想是将最长公共子序列转成最长上升子序列,然后用最长上升子序列nlgn的算法求解.更具体的解释可以参看这篇博文:最长公共子序列(nlogn) 代码如下: #include<iostream> #include<cstring> #include<cstdio> #i

LCS 求最长公共子序列

最长公共子序列不需要字符连续出现和字串不同 //LCS 求最长公共子串模板题  Common Subsequence 描述 A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, ..., xm> another sequence Z = <z1, z2, ..., zk> is

hdu 1159 Common Subsequence(最长公共子序列 DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159 Common Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 25416    Accepted Submission(s): 11276 Problem Description A subsequence of