zoukankan      html  css  js  c++  java
  • 经典算法-最长公共子序列(LCS)与最长公共子串(DP)

    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
    */
  • 相关阅读:
    Windows Internals学习笔记(八)IO系统
    FPGA相关术语(一)
    Bilinear Filter
    总线与接口
    GPIO相关知识
    .NET IL学习笔记(一)
    Windows Internals学习笔记(七)Image Loader
    Windows Internals学习笔记(五)Synchronization
    struts2官方 中文教程 系列五:处理表单
    struts2官方 中文教程 系列四:Action
  • 原文地址:https://www.cnblogs.com/Roni-i/p/10395089.html
Copyright © 2011-2022 走看看