LCS最长公共子序列 动态规划方法 递归与非递归算法

首先我们要明确一点,LCS可以从第一个字母进行匹配也可以从最后一个字母进行匹配,a->b->c->d  a到d的距离就是a到b的距离加上b到d的距离,

递归算法

import java.util.Scanner;

public class LCS {
 static int LCS_LENGTH(int[][] c, char a[], char[] b, int m, int n) {
  if (m == 0 || n == 0) {
   //有一个为0说明前面不可能有匹配相等的,因此c[m][n] = 0
   c[m][n] = 0;
  } else {
   if (a[m – 1] == b[n – 1]) {
    //相等说明这个字符匹配成功,在往前递归
    c[m][n] = LCS_LENGTH(c, a, b, m – 1, n – 1) + 1;
   } else {//本字符没匹配成功,看看哪一个字符串需要前移
    int i1 = LCS_LENGTH(c, a, b, m – 1, n);
    int i2 = LCS_LENGTH(c, a, b, m, n – 1);
    c[m][n] = i1 > i2 ? i1 : i2;// 三元表达式
   }

  }
  return c[m][n];
 }

 static void LCS_RESULT(int[][] c, int length, char a[], int m, int n,
   char[] str) {
  if (m == 0 || n == 0) {
   return;
  } else {
   if (c[m][n] == c[m][n – 1]) {
//如果才c[m][n] == c[m][n – 1]说明不包括c[m][n],往前递归
    LCS_RESULT(c, length, a, m, n – 1, str);
   } else if (c[m][n] == c[m – 1][n]) {
    //如果才c[m][n] == c[m – 1][n]说明不包括c[m][n],往前递归
    LCS_RESULT(c, length, a, m – 1, n, str);
   } else {
    //说明包括c[m][n],将这个位置的字符赋给str[]
    str[length – 1] = a[m – 1];
    LCS_RESULT(c, length – 1, a, m – 1, n – 1, str);
   }
  }

 }

 public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);
  String s1 = scanner.nextLine();
  String s2 = scanner.nextLine();
  char[] a = s1.toCharArray();//第一个字符串
  char[] b = s2.toCharArray();//第二个字符串
  int m = a.length;//第一个字符串长度
  int n = b.length;//第二个字符串长度
  int c[][] = new int[m + 1][n + 1];//记录第c[m][n]之前的最大长度
  int k = LCS_LENGTH(c, a, b, m, n);//最大长度
  char str[] = new char[k];//最长公共字符序列
  LCS_RESULT(c, k, a, m, n, str);

  for (char cr : str) {
   System.out.print(cr);
  }
  System.out.println();
  for (int c1[] : c) {
   for (int c2 : c1) {
    System.out.print(c2);
   }
   System.out.println();
  }
 }
}
非递归算法

import java.util.Scanner;

public class LCS2 {
 static int LCS_LENGTH(int[][] c, char a[], char[] b, int m, int n) {
  for(int i=0;i<=m;i++)c[i][0]=0;
  for(int i=0;i<=n;i++)c[0][i]=0;
  for(int i=1;i<=m;i++){
   for(int j=1;j<=n;j++){
    if(a[i-1]==b[j-1]){
     c[i][j]=c[i-1][j-1]+1;
    }else{
     if(c[i-1][j]>=c[i][j-1]){
      c[i][j]=c[i-1][j];
      
     }else{
      c[i][j]=c[i][j-1];
     }
    }
   }
  }
  return c[m][n];
 }

 static void LCS_RESULT(int[][] c, int length, char a[], int m, int n,
   char[] str) {
  while(length>0){
   if(c[m][n]==c[m-1][n]){
    m=m-1;
   }else if(c[m][n]==c[m][n-1]){
    n=n-1;
   }else{
    str[length-1]=a[m-1];
    m=m-1;
    length=length-1;
    n=n-1;
   }
  }

 }
 public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);
  String s1 = scanner.nextLine();
  String s2 = scanner.nextLine();
  char[] a = s1.toCharArray();
  char[] b = s2.toCharArray();
  int m = a.length;
  int n = b.length;
  int c[][] = new int[m + 1][n + 1];
  int k = LCS_LENGTH(c, a, b, m, n);
  char str[] = new char[k];
  LCS_RESULT(c, k, a, m, n, str);

  for (char cr : str) {
   System.out.print(cr);
  }
  System.out.println();
  for (int c1[] : c) {
   for (int c2 : c1) {
    System.out.print(c2);
   }
   System.out.println();
  }
 }
}



    原文作者:递归算法
    原文地址: https://blog.csdn.net/ch1209498273/article/details/46403325
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞