LCS算法

一.问题描述

  如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中,则字符串一称之为字符串二的子串。
  注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中。
二.最长公共子序列的结构
  最长公共子序列的结构有如下表示:
  设序列X=<x1, x2, …, xm>和Y=<y1, y2, …, yn>的一个最长公共子序列Z=<z1, z2, …, zk>,则:

  • 若xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的最长公共子序列;
  • 若xm≠yn且zk≠xm ,则Z是Xm-1和Y的最长公共子序列;
  • 若xm≠yn且zk≠yn ,则Z是X和Yn-1的最长公共子序列。

  其中Xm-1=<x1, x2, …, xm-1>,Yn-1=<y1, y2, …, yn-1>,Zk-1=<z1, z2, …, zk-1>。
三.子问题的递归结构
  由最长公共子序列问题的最优子结构性质可知,要找出X=<x1, x2, …, xm>和Y=<y1, y2, …, yn>的最长公共子序列,可按以下方式递归地进行:当xm=yn时,找出Xm-1和Yn-1的最长公共子序列,然后在其尾部加上xm(=yn)即可得X和Y的一个最长公共子序列。当xm≠yn时,必须解两个子问题,即找出Xm-1和Y的一个最长公共子序列及X和Yn-1的一个最长公共子序列。这两个公共子序列中较长者即为X和Y的一个最长公共子序列。
  由此递归结构容易看到最长公共子序列问题具有子问题重叠性质。例如,在计算X和Y的最长公共子序列时,可能要计算出X和Yn-1及Xm-1和Y的最长公共子序列。而这两个子问题都包含一个公共子问题,即计算Xm-1和Yn-1的最长公共子序列。
  与矩阵连乘积最优计算次序问题类似,我们来建立子问题的最优值的递归关系。用c[i,j]记录序列Xi和Yj的最长公共子序列的长度。其中Xi=<x1, x2, …, xi>,Yj=<y1, y2, …, yj>。当i=0或j=0时,空序列是Xi和Yj的最长公共子序列,故c[i,j]=0。其他情况下,由定理可建立递归关系如下:LCS源代码

import java.io.FileInputStream;

public class LCS {
    public static void LCS_LENGHT(String str1, String str2) {
        char[] arr1 = str1.toCharArray();
        char[] arr2 = str2.toCharArray();
        int[][] matri = new int[arr1.length + 1][arr2.length + 1];
        for (int i = 1; i <=arr1.length; i++) {
            for (int j = 1; j <=arr2.length; j++) {
                if (arr1[i - 1] == arr2[j - 1]) {
                    matri[i][j] = matri[i - 1][j - 1] + 1;
                } else if (matri[i - 1][j] >=matri[i][j - 1]) {
                    matri[i][j]=matri[i-1][j];
                } else {
                    matri[i][j]=matri[i][j-1];
                }
            }
        }
        PRINT_LCS(matri, arr1, arr2, arr1.length,arr2.length);
    }

    public static void PRINT_LCS(int[][] matri,char[] x,char[] y,int xlength,int ylength){
        if(xlength==0||ylength==0){
            return;
        }
        if(x[xlength-1]==y[ylength-1]){
            PRINT_LCS(matri, x, y, xlength-1, ylength-1);
            System.out.println(x[xlength-1]);
        }else if(matri[xlength - 1][ylength] >=matri[xlength][ylength - 1]){
            PRINT_LCS(matri, x, y, xlength-1, ylength);
        }else {
            PRINT_LCS(matri, x, y, xlength, ylength-1);
        }
    }

    public static void main(String[] args) {
        String str1="ABCBDAB";
        String str2="BDCABA";
        LCS_LENGHT(str1, str2);
    }
}

时间: 2024-10-05 03:50:04

LCS算法的相关文章

WOJ 1047 LCS problem (LCS 算法总结 )

http://acm.whu.edu.cn/land/problem/detail?problem_id=1047 Description Recently, Flymouse reads a book about Algorithm and Data Structure. The book reads: there are two types of LCS Problems. One is Longest Common Subsequence problem. By the way of Dy

LCS算法思想

LCS问题就是求两个字符串最长公共子串的问题.解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0.然后求出对角线最长的1序列,其对应的位置就是最长匹配子串的位置.下面是字符串21232523311324和字符串312123223445的匹配矩阵,前者为X方向的,后者为Y方向的.不难找到,红色部分是最长的匹配子串.通过查找位置我们得到最长的匹配子串为:212320 0 0 1 0 0 0 1 1 0 0 1 0 0 00 1 0 0 0 0 0 0 0

非动态规划实现LCS算法

LCS(最长公共子串 longest common subsequence)一般都会采用动态规划的算法来实现,算法的时间复杂度大概是O(x2),  另外需要一个x2的额外空间, 这个算法这里我不做说明,给个讲得不错的教程地址 LCS教程 这边博文里我将给出一个不采用动态规划的算法,并且时间复杂度和动态规划算法相同,还不会使用到额外的空间,空间复杂度为O(0). 思路: 假设存在两个字符串l和r, 并且strlen(l) <= strlen(r), 将l字符串想象成一辆车, 将r字符串想象成公路,

LCS 算法实现

动态规划算法 #include <iostream> #include <string.h> #include <algorithm> #include <math.h> using namespace std; #define MAXSTRLEN 20 int Lcs(char x[], char y[], int path[][MAXSTRLEN])//求序列x和y的最长公共子序列,path保存路径指向,以方便打印公共子序列 { int i, j; in

求两个字符串最大子串的lcs算法

/************************************************************************* > File Name: lcs.c > Author: dingzhengsheng > Mail: [email protected] > Created Time: 2015年05月20日 星期三 16时07分50秒 > Version: v0.01 > Description: > History: ****

LCS 算法

f[i][j] 一定是 f[i-1][j] 和 F[i][j-1] 转移过来的. 如果 把 a 串  看成字符数组 s1[], b 串 看成 s2[] ; 则: 如果 s1[i]!=s2[j] 那么 从 f[i-1][j] 和 f[i][j-1] 取一个最大值 记录到 F[i] [j]. 代码如下: f[i][j]=max(f[i-1][j],f[i][j-1]); 如果 s1[i] == s2[j] 那么 f[i][j] 是由 F[i-1][j-1]+1 推来的: 用dp方程式可以推出,如图:

LCS算法改进

public static void Lcs_Length(String X,String Y,int c[][]) { X=" "+X; Y=" "+Y; for(int i=1;i<X.length();i++) { c[i][0]=0; } for(int j=0;j<Y.length();j++) { c[0][j]=0; } for(int i=1;i<X.length();i++) { for(int j=1;j<Y.length

LCS(最长公共子序列)动规算法正确性证明

今天在看代码源文件求diff的原理的时候看到了LCS算法.这个算法应该不陌生,动规的经典算法.具体算法做啥了我就不说了,不知道的可以直接看<算法导论>动态规划那一章.既然看到了就想回忆下,当想到算法正确性的时候,发现这个算法的正确性证明并不好做.于是想了一段时间,里面有几个细节很trick,容易陷进去.想了几轮,现在把证明贴出来,有异议的可以留言一起交流. 先把一些符号和约定说明下: 假设有两个数组,A和B.A[i]为A的第i个元素,A(i)为有A的第一个元素到第i个元素所组成的前缀.m(i,

最长递增子序列 O(NlogN)算法

https://www.felix021.com/blog/read.php?entryid=1587&page=3&part=1 感谢作者! 标题:最长递增子序列 O(NlogN)算法 出处:Blog of Felix021 时间:Wed, 13 May 2009 04:15:10 +0000 作者:felix021 地址:https://www.felix021.com/blog/read.php?1587  内容: 今天回顾WOJ1398,发现了这个当时没有理解透彻的算法. 看了好久