动态规划java LCS_Java-LCS最长公共子序列(动态规划实现)

一个序列S任意删除若干个字符得到新序列T,则T称为S的子序列。若两个序列X和Y的公共子序列中,长度最长的那个字序列称为X和Y的最长公共子序列(LCS)。

Xi表示字符串的前i个字符,Yj表示字符串的前j个字符,它们的公共子序列记为:LCS(X,Y),即Z=。利用动态规划来处理该问题,此时分为两种情况:

1)Xm == Yn(最后一个字符相同),则Xm与Yn的最长公共子序列Zk的最后一个字符必定相同,即:Xm == Yn == Zk。此时的表达式为:

LCS(Xm, Yn) = LCS(Xm-1, Yn-1) +Xm             (**公式一**)

2)Xm != Yn(最后一个字符不相同),则Xm与Yn的最长公共子序列Zk的最后一个字符就存在两种肯能,即:Xm == Zk 或者 Yn == Zk。此时的表达式存在两种情况,如下:

LCS(Xm, Yn) = LCS(Xm-1, Yn) 或者 LCS(Xm, Yn) = LCS(Xm, Yn-1)。则最终的表达式为:

LCS(Xm, Yn) = MAX{LCS(Xm-1, Yn), LCS(Xm, Yn-1)}     (**公式二**)

在寻找最长公共子序列的过程中利用数组Array来记录Xi和Yj的最长公共子序列的长度。当i=0或j=0时,Array数组记录为0。当i>0,j>0并且Xi==Yj时,利用公式一,当i>0,j>0,并且Xi!= Yj时,利用公式二。得到如下公式:

Array(i,j) = 0;                                          当i=0或者j=0;

Array(i,j) = Array(i-1,j-1);                        当i>0,j>0&&Xi==Yj;

Array(i,j) = max{Array(i-1,j),Array(I,j-1)}      当i>0,j>0&&Xi!=Yj

package 字符串;

import java.util.Scanner;

import java.util.Stack;

/**

* 任意输入两个字符串,求出这两个字符串的公共子序列

* */

public class 最长公共子序列 {

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

String x = sc.next();

String y = sc.next();

getLCS(x,y);

}

public static void getLCS(String x, String y){

char[] s1 = x.toCharArray();

char[] s2 = y.toCharArray();

int[][] array = new int[x.length()+1][y.length()+1];//此处的棋盘长度要比字符串长度多加1,需要多存储一行0和一列0

for(int j = 0; j < array[0].length; j++){//第0行第j列全部赋值为0

array[0][j] = 0;

}

for(int i = 0; i < array.length; i++){//第i行,第0列全部为0

array[i][0] = 0;

}

for(int m = 1; m < array.length; m++){//利用动态规划将数组赋满值

for(int n = 1; n < array[m].length; n++){

if(s1[m - 1] == s2[n - 1]){

array[m][n] = array[m-1][n-1] + 1;//动态规划公式一

}else{

array[m][n] = max(array[m -1][n], array[m][n -1]);//动态规划公式二

}

}

}

//for(int m = 0; m < array.length; m++){//将数组赋满值,这样可以从右下角开始遍历找出最大公共子序列

//for(int n = 0; n < array[m].length; n++){

//System.out.print(array[m][n]);

//}

//System.out.println();

//}

Stack stack = new Stack();

int i = x.length() - 1;

int j = y.length() - 1;

while((i >= 0) && (j >= 0)){

if(s1[i] == s2[j]){//字符串从后开始遍历,如若相等,则存入栈中

stack.push(s1[i]);

i--;

j--;

}else{

if(array[i+1][j] > array[i][j+1]){//如果字符串的字符不同,则在数组中找相同的字符,注意:数组的行列要比字符串中字符的个数大1,因此i和j要各加1

j--;

}else{

i--;

}

}

}

while(!stack.isEmpty()){//打印输出栈正好是正向输出最大的公共子序列

System.out.print(stack.pop());

}

}

public static int max(int a, int b){//比较(a,b),输出大的值

return (a > b)? a : b;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值