ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

经典算法-最长公共子序列(LCS)与最长公共子串(DP)

2019-02-18 13:39:53  阅读:237  来源: 互联网

标签:String int max len1 len2 length 公共 最长 LCS


 

 

public static int lcs(String str1, String str2) {  
    int len1 = str1.length();  
    int len2 = str2.length();  
    int c[][] = new int[len1+1][len2+1];  
    for (int i = 0; i <= len1; i++) {  
        for( int j = 0; j <= len2; j++) {  
            if(i == 0 || j == 0) {  
                c[i][j] = 0;  
            } else if (str1.charAt(i-1) == str2.charAt(j-1)) {  
                c[i][j] = c[i-1][j-1] + 1;  
            } else {  
                c[i][j] = max(c[i - 1][j], c[i][j - 1]);  
            }  
        }  
    }  
    return c[len1][len2];  
}  

 

public class LCSProblem
{
  public static void main(String[] args)
  {
    //保留空字符串是为了getLength()方法的完整性也可以不保留
    //但是在getLength()方法里面必须额外的初始化c[][]第一个行第一列
    String[] x = {"", "A", "B", "C", "B", "D", "A", "B"};
    String[] y = {"", "B", "D", "C", "A", "B", "A"};
    int[][] b = getLength(x, y);
    Display(b, x, x.length-1, y.length-1);
  }
  /**
   * @param x
   * @param y
   * @return 返回一个记录决定搜索的方向的数组
   */
  public static int[][] getLength(String[] x, String[] y)
  {
    int[][] b = new int[x.length][y.length];
    int[][] c = new int[x.length][y.length];
    for(int i=1; i<x.length; i++)
    {
      for(int j=1; j<y.length; j++)
      {
        //对应第一个性质
        if( x[i] == y[j])
        {
          c[i][j] = c[i-1][j-1] + 1;
          b[i][j] = 1;
        }
        //对应第二或者第三个性质
        else if(c[i-1][j] >= c[i][j-1])
        {
          c[i][j] = c[i-1][j];
          b[i][j] = 0;
        }
        //对应第二或者第三个性质
        else
        {
          c[i][j] = c[i][j-1];
          b[i][j] = -1;
        }
      }
    }
    return b;
  }
  //回溯的基本实现,采取递归的方式
  public static void Display(int[][] b, String[] x, int i, int j)
  {
    if(i == 0 || j == 0)
      return;
    if(b[i][j] == 1)
    {
      Display(b, x, i-1, j-1);
      System.out.print(x[i] + " ");
    }
    else if(b[i][j] == 0)
    {
      Display(b, x, i-1, j);
    }
    else if(b[i][j] == -1)
    {
      Display(b, x, i, j-1);
    }
  }
}

 

 

 

public static int lcs(String str1, String str2) {  
    int len1 = str1.length();  
    int len2 = str2.length();  
    int result = 0;     //记录最长公共子串长度  
    int c[][] = new int[len1+1][len2+1];  
    for (int i = 0; i <= len1; i++) {  
        for( int j = 0; j <= len2; j++) {  
            if(i == 0 || j == 0) {  
                c[i][j] = 0;  
            } else if (str1.charAt(i-1) == str2.charAt(j-1)) {  
                c[i][j] = c[i-1][j-1] + 1;  
                result = max(c[i][j], result);  
            } else {  
                c[i][j] = 0;  
            }  
        }  
    }  
    return result;  
}  

 

public class stringCompare {
  //在动态规划矩阵生成方式当中,每生成一行,前面的那一行就已经没有用了,因此这里只需使用一维数组,而不是常用的二位数组
  public static void getLCString(char[] str1, char[] str2) {
    int len1, len2;
    len1 = str1.length;
    len2 = str2.length;
    int maxLen = len1 > len2 ? len1 : len2;
    int[] max = new int[maxLen];// 保存最长子串长度的数组
    int[] maxIndex = new int[maxLen];// 保存最长子串长度最大索引的数组
    int[] c = new int[maxLen];
    int i, j;
    for (i = 0; i < len2; i++) {
      for (j = len1 - 1; j >= 0; j--) {
        if (str2[i] == str1[j]) {
          if ((i == 0) || (j == 0))
            c[j] = 1;
          else
            c[j] = c[j - 1] + 1;//此时C[j-1]还是上次循环中的值,因为还没被重新赋值
        } else {
          c[j] = 0;
        }
        // 如果是大于那暂时只有一个是最长的,而且要把后面的清0;
        if (c[j] > max[0]) {
          max[0] = c[j];
          maxIndex[0] = j;
          for (int k = 1; k < maxLen; k++) {
            max[k] = 0;
            maxIndex[k] = 0;
          }
        }
        // 有多个是相同长度的子串
        else if (c[j] == max[0]) {
          for (int k = 1; k < maxLen; k++) {
            if (max[k] == 0) {
              max[k] = c[j];
              maxIndex[k] = j;
              break; // 在后面加一个就要退出循环了
            }
          }
        }
      }
      for (int temp : c) {
        System.out.print(temp);
      }
      System.out.println();
    }
    //打印最长子字符串
    for (j = 0; j < maxLen; j++) {
      if (max[j] > 0) {
        System.out.println("第" + (j + 1) + "个公共子串:");
        for (i = maxIndex[j] - max[j] + 1; i <= maxIndex[j]; i++)
          System.out.print(str1[i]);
        System.out.println(" ");
      }
    }
  }
  public static void main(String[] args) {
    String str1 = new String("binghaven");
    String str2 = new String("jingseven");
    getLCString(str1.toCharArray(), str2.toCharArray());
  }
}

/*
000000000
010000000
002000001
000300000
000000000
000000010
000000100
000000020
001000003
第1个公共子串:
ing
第2个公共子串:
ven
*/

 

标签:String,int,max,len1,len2,length,公共,最长,LCS
来源: https://www.cnblogs.com/Roni-i/p/10395089.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有