LCS问题

本文详细介绍了LCS(最长公共子序列)问题,包括最长公共子串和子序列的定义及其区别。LCS问题在生物信息学、版本控制等领域有广泛应用。动态规划是解决LCS问题的常用方法,具有时间复杂度,可以通过优化减少空间复杂度。对于最长公共子序列问题,还需要额外信息来重构序列。
摘要由CSDN通过智能技术生成

LCS问题

1. 简介

LCS通常是指Longest Common Subsequence, 但是也可代指Longest Common Substring。子串是一种特殊的子序列,子串和子序列的区别就是字串要求是组成子串的
各字符是连续的,而子序列仅仅要求各字符的下标是递增的即可。举个例子,如helloworldworld是子串(也是子序列), hw不是子串是子序列。

LCS问题就是在若干(这里是两个)字符串中,找到最长的一个字符串p, 这个p是那些字符串的子串(子序列)。LCS问题的意义之一就是去衡量若干字符串的相似度,例如在生物信息学
中有DNA序列的问题,比如序列a = "ATGATAGATAGATAG", 序列b="TGGGCCGAGAAGCGAGA",需要一种去衡量ab相似度的方法,那么最长公共子序列就可以作为一种衡量方法。
除此之外,在软件开发领域中的版本控制系统(典型的就是Git),比较同一个文件不同时刻的差异的时候,就需要利用到这个方法。

例如下图就是Git上面的两次不同时刻对同一个文件的快照的对比图,我们可以看到,系统把两次的差异标示出来了。而原来位置、内容相同的部分没有标示。这个就可以通过
LCS问题的解决,来找到最长的公共子序列部分,就是作为公共的、未发生改变部分;剩下的就是改变的部分,应该标示出来。

这里写图片描述

同理基于这个,我们还可以简单的比较两篇文章的相似度来检查雷同、抄袭的情况,这么看来,LCS问题的还是和我们日常比较相关的。

解决LCS问题依靠暴力(brute force)的求解时间复杂度是指数级别的,因此不太现实,由于问题的本身的最优解具有最优子结构特征,因此原问题的求解可以化为多个子问题的求解;另外子问题的求解存在重叠的情况,这恰好是适合动态规划求解的问题的第二个特征:存在重叠的子问题求解过程,因此适合利用动态规划来求解,这个也是较常见的解决LCS问题的方法,时间复杂度为O(n*m),动态规划易于编写,但是时间复杂度较高;另外更高级的还存在一种线性复杂度的O(n+m)的解法,就是Suffix Tree,不过这种方法的缺点是程序难以编制。因此在日常的编码中,动态规划已经够用了。

2. 最长公共子串问题

设dp[i][j]表示s[0~i]和t[0~j]的最长公共子串的长度,对于两个字符串的最长公共子串问题的最优解,最优解存在如下结构:

dp[i][j] = 1 (i == 0 || j == 0)
dp[i][j] = dp[i-1][j-1] + 1;(s[i] == t[j] && i > 0 && j > 0);
dp[i][j] = 0;(s[i] != t[j])

上述等式建立了原问题和子问题的关系(此类证明可用反证法),剩下的就是编码了。

public static List<String> findLongestLCS(String s, String t) {
   char[] schs = s.toCharArray();
   char[] tchs = t.toCharArray();
   int m = s.length(), n = t.length();
   int[][] dp = new int[m][n];
   int maxSize = 0;
   List<Integer> indexs = new ArrayList<>();//存储最长公共子串的在原始串中结束位置

   for (int i = 0; i < m; i++)
     for (int j = 0; j < n; j++) {
       if (schs[i] == tchs[j]) {
         if (i == 0 || j &
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值