最长公共子序列 动态规划
若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。
给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。
给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。
@SuppressWarnings("all")
public class Longest_common_subsequence {//最长公共子序列 动态规划
public static void main(String args[]){
char []a = {'A','C','T','C','C','T','A','G'};
char []b = {'C','A','T','T','C','A','G','C'};
int [][]arr = new int[a.length + 1][b.length + 1];
int [][]arr1 = lcslength(a.length + 1,b.length + 1,a,b,arr);//记录公共子序列的位置
System.out.print("最长公共子序列为:");
lcs(arr1.length - 1,arr1[0].length - 1,a,arr1);
}
static void lcs(int i,int j,char []a,int [][]arr){//输出公共子序列
if(i == 0||j == 0)return;
if(arr[i][j] == 1){
lcs(i - 1,j - 1,a,arr);//先递归,在输出
System.out.printf("%c",a[i - 1]);
}
else if(arr[i][j] == 2){
lcs(i - 1,j,a,arr);
}
else {
lcs(i,j - 1,a,arr);
}
}
static int[][]lcslength(int n,int m,char []a,char []b,int [][]arr){//寻找公共子序列并记录
int [][]c = new int[n][m];
for(int i = 0;i < n;i++){//初始化 多余
c[i][0] = 0;
}
for(int j = 0;j < n;j++){
c[0][j] = 0;
}
for(int i = 1;i < c.length;i++){
for(int j = 1;j < c[0].length;j++){
if(a[i - 1] == b[j - 1]){//1表示左上角
c[i][j] = c[i - 1][j - 1] + 1;
arr[i][j] = 1;
}
else{//2 表示上方
if(c[i - 1][j] > c[i][j - 1]){
c[i][j] = c[i -1][j];
arr[i][j] = 2;
}
else{//3 表示左边
c[i][j] = c[i][j - 1];
arr[i][j] = 3;
}
}
}
}
System.out.println("最长公共子序列长度为:" + c[n - 1][m - 1]);
return arr;
}
}
参考博客:
https://blog.csdn.net/weixin_40673608/article/details/84262695?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163937751116780366598863%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163937751116780366598863&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-2-84262695.pc_search_result_cache&utm_term=%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%AD%90%E5%BA%8F%E5%88%97+%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92&spm=1018.2226.3001.4187