zoukankan      html  css  js  c++  java
  • 最长公共子序列问题

    输入:两个字符串序列

    输出:两个字符串序列的最长公共子序列的长度和子序列

    例如:

    输入:str1="BDCABA",   str2="ABCBDAB"

    输出:4   “BDAB”

    若此问题采用暴力法求解:枚举str1的每个子序列str,检查str是否为序列str2的子序列,记录当前找到的长度的最大的公共子序列。可以看出暴力法的效率十分低下,并且每次检查str是否为str2的子序列的时间复杂度为O(n),然而str有2m 个子序列,因此采用暴力法的最坏时间复杂度为O(n2m)。

    针对此问题可以采用动态规划去做。

    令C[i,j]表示str1的前i项和str2的前j项的最长公共子序列的长度,则会有

    计算长度算法为LcsLength

    打印最长公共子串的算法为LcsPrint

    用Java语言的具体实现代码如下:

     1 public class LcsLength {
     2     public static int lcslength(String str1,String str2,char b[][]){
     3         int m=str1.length();
     4         int n=str2.length();
     5         int c[][]=new int[m+1][n+1];                               //统计长度
     6         
     7         for(int i=0;i<=m;i++)c[i][0]=0;
     8         for(int j=0;j<=n;j++)c[0][j]=0;
     9         for(int i=1;i<=m;i++)
    10             for(int j=1;j<=n;j++)
    11                 if(str1.charAt(i-1)==str2.charAt(j-1)){c[i][j]=c[i-1][j-1]+1;b[i][j]='X';}    //X表示左上箭头
    12                 else if(c[i-1][j]>=c[i][j-1]){c[i][j]=c[i-1][j];b[i][j]='U';}                 //U表示向上箭头
    13                 else {c[i][j]=c[i][j-1];b[i][j]='L';}                                         //L表示向左箭头
    14         return c[m][n];                                                                      //返回最长子序列的长度
    15     }
    16     
    17     public static void lcsprint(char B[][],String str1,int m,int n){
    18         if(m==0||n==0)return;
    19         if(B[m][n]=='X'){lcsprint(B,str1,m-1,n-1);System.out.print(str1.charAt(m-1));}
    20         else if(B[m][n]=='U')lcsprint(B,str1,m-1,n);
    21         else lcsprint(B,str1,m,n-1);
    22     }
    23     
    24     public static void main(String[] args) {
    25         // TODO 自动生成的方法存根
    26         String str1 = new String("BDCABA");
    27         String str2 = new String("ABCBDAB");
    28         System.out.println("第一个字符串str1为:"+str1);
    29         System.out.println("第二个字符串str2为:"+str2);
    30         int m=str1.length();
    31         int n=str2.length();
    32         char B[][]=new char[m+1][n+1];
    33         System.out.println("最长公共子序列的长度为:"+lcslength(str1,str2,B));
    34         System.out.print("最长公共子序列为:");
    35         lcsprint(B,str1,m,n);
    36 
    37     }
    38 
    39 }
    View Code

    输出为:

    第一个字符串str1为:BDCABA
    第二个字符串str2为:ABCBDAB
    最长公共子序列的长度为:4
    最长公共子序列为:BDAB

  • 相关阅读:
    【转】XP下安装IIS6.0的办法
    设计模式学习笔记十:单例模式(Singleton Pattern)
    linq学习笔记(2):DataContext
    设计模式学习笔记十二:桥接模式(Bridge Pattern)
    英文版c#数据结构
    linq学习笔记(3):Where
    一步步学习WCF(1):Hello
    linq学习笔记(5):Count/Sum/Min/Max/Avg
    [转]Asp.Net 面试题目收集
    从谷歌公司发现的十个至理名言
  • 原文地址:https://www.cnblogs.com/guozhenqiang/p/5425075.html
Copyright © 2011-2022 走看看