zoukankan      html  css  js  c++  java
  • [算法]最长公共子序列--LCS(Longest Common Subsequence)

    1.简单的题目描述:

    如两个 字符串的 BDCABA  与 ABCBDAB,求最长的公共子序列。

    PS:最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)的区别为:子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列;也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续

    2.解法:DP -动态规划

    str1[m] =BDCABA

          下标:012345

    str2[m] =ABCBDAB

          下标:0123 4 5 6

    C[maxlen][maxlen] 来存放结果

    原理:c(i,j) 表示str[i-1],str[j-1] 的LCS 长度

    得到:

    lcs_1

    回溯输出最长公共子序列过程:

    flow

    如何输出LCS序列:

    我们可以从后往前去找:
    
    原序列:
    
    str1[i].B D C A B A
    
    str2[j].A B C B D A B
    
    我们这样考虑:最后的 A B,不相等,所以 LCS 存在于『B D C A B A 和 A B C B D A 』 或 『B D C A B  和 A B C B D A B』中 就是:str[6-1] != str[7-1]
    
    如果 c[i][j-1] = c[i-1][j] 那就表明『B D C A B A 和 A B C B D A 』 或 『B D C A B  和 A B C B D A B』的 LCS 长度一样
    
    此时 选那个都一样:

    如果str[i] == str[j] 就表示 srt[i]要输出,如果 c[i][j-1] = c[i-1][j] 那就表明『B D C A B A 和 A B C B D A 』 或 『B D C A B 和 A B C B D A B』的 LCS 长度一样
    此时继续往下面去找 str[i] == str[j]

      

    构建一个数组来倒序的存放LCS

    我写的算法(C):--问题1:没有解决所有LCS 的输出,只输出一个且是倒序的

    /*
     * =====================================================================================
     *
     *       Filename:  5.c
     *
     *    Description:  RT
     *
     *        Version:  1.0
     *        Created:  2014-4-27 星期日 11:19:37
     *       Revision:  none
     *       Compiler:  gcc
     *
     *         Author:  Rainboy (mn), 597872644@qq.com
     *        Company:  NONE
     *
     * =====================================================================================
     */
    
    #include <stdio.h>
    #include <string.h>
    
    #define maxlen 200
    int c[200][200];
    char str1[maxlen]="BDCABA",str2[maxlen]="ABCBDAB";
    char buffer[maxlen]={0};
    int main (int argc, char *argv[]) {
        memset(c,0,sizeof(c));
        int i,j;
        for(i=0;i<strlen(str1);i++)                 /* 开始DP 运算 */
            for (j=0;j<strlen(str2);j++) {
                if(str1[i]==str2[j])
                {
                    c[i+1][j+1]=c[i][j]+1;
                }
                else if(c[i+1][j] > c[i][j+1])
                    c[i+1][j+1] = c[i+1][j];
                else
                    c[i+1][j+1] =c[i][j+1];
    
            }
        
    
        for(j=0;j<=strlen(str2);j++){               /* 打印c[i][j] */
            for (i=0;i<=strlen(str1);i++) {
                printf("%4d",c[i][j]);
            }
            printf("
    ");
        }
            printf("
    ");
            printf("
    ");
            
            for(i=strlen(str1),j=strlen(str2);i>0 && j>0;) /* 倒序打印一个LCS */
            {
                if(str1[i-1]==str2[j-1])
                {
                   printf("%c",str1[i-1]);
                   i--; j--;
                }
                else if(c[i][j-1] >= c[i-1][j])
                {
                    j--;
                }
                else {
                    i--;
                }
            }
        printf("
    ");
        printf("LCS is %d
    ",c[strlen(str1)][strlen(str2)]);
        return 0;
    }

    算法(PAS):

    const maxlen = 200;
    var i,j:integer;
    c:array[0..maxlen,0..maxlen] of integer;
    x,y,z:string;
    begin
    x:='BDCABA';
    y:='ABCBDAB';
    fillchar(c,sizeof(c),0);
    for i:=1 to length(x) do
            for j:=1 to length(y) do
            if x[i] = y[j]
            then c[i,j]:=c[i-1,j-1]+1
            else if c[i-1,j]  > c[i,j-1]
                    then c[i,j]:=c[i-1,j]
                    else c[i,j]:=c[i,j-1];
          i:=length(x);
          j:=length(y);
          z:='';
          writeln(i:4,j:4);
          writeln(c[i,j]);
        //  :shu chu LCS
          while (i>0) and  (j>0) do
          if x[i]= y[j]
          then begin z:=x[i]+z;i:=i-1;j:=j-1 end
          else if c[i-1,j]> c[i,j-1]
                    then i:=i-1
                    else j:=j-1;
           if z<>'' then writeln(z);
    readln;
    end.
  • 相关阅读:
    JVM参数配置
    域渗透命令
    相对路径绝对路径
    ESPCMS的CSRF添加管理员账号
    nmap脚本nse的使用
    Nmap简单的漏扫
    MS08-067
    lcx用法
    给自己的服务器传文件 转自别人
    突破大文件上传 和内网ip的端口转发
  • 原文地址:https://www.cnblogs.com/rainboy/p/3696126.html
Copyright © 2011-2022 走看看