使用动态规划找出2个字符串的最长公共子序列
package com.prac;
/*
* 计算最长公共子序列的长度,并返回该最长公共子序列
*/
public class LongestCommonSubStr {
/*
* map用来记录最长公共子序列的长度
*/
public static int findLCS(char[] str1,char[] str2,int[][] map){
int len1=str1.length;
int len2=str2.length;
for(int i=0;i<len1+1;i++)
map[0][i]=0;
for(int i=0;i<len2+1;i++)
map[i][0]=0;
for(int i=1;i<len2+1;i++){
for(int j=1;j<len1+1;j++){
if(str1[j-1] == str2[i-1]){
map[i][j]=map[i-1][j-1]+1;
}
else{
map[i][j]=Math.max(map[i-1][j], map[i][j-1]);
}
}
}
return map[len2][len1];
}
/*
* marks用来记录当前最长公共子序列的最后一个字符的来源
*/
public static int findLCS(char[] str1,char[] str2,int[][] map,int[][] marks){
int len1=str1.length;
int len2=str2.length;
for(int i=0;i<len1+1;i++)
map[0][i]=0;
for(int i=0;i<len2+1;i++)
map[i][0]=0;
for(int i=1;i<len2+1;i++){
for(int j=1;j<len1+1;j++){
if(str1[j-1] == str2[i-1]){
map[i][j]=map[i-1][j-1]+1;
marks[i][j]=3;
}
else{
map[i][j]=Math.max(map[i-1][j], map[i][j-1]);
if(map[i-1][j]>map[i][j-1])
marks[i][j]=1;
else
marks[i][j]=2;
}
}
}
return map[len2][len1];
}
public static String getLCS(char[] str1,char[] str2,int[][] marks){
StringBuilder sb=new StringBuilder();
int len1=str1.length;
int len2=str2.length;
int i=len2,j=len1;
while(i>0 && j>0){
if(marks[i][j]==3){
sb.append(str2[i-1]);
i--;
j--;
}
else if(marks[i][j]==2){
j--;
}
else if(marks[i][j]==1){
i--;
}
else{
System.out.println("error 001");
System.exit(-1);
}
}
return sb.reverse().toString();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
char[] str1="1qw20e3r45tyu".toCharArray();
char[] str2="aa1s2s3d4f5g0h".toCharArray();
int[][] map=new int[str2.length+1][str1.length+1];
int[][] marks=new int[str2.length+1][str1.length+1];
int result=findLCS(str1,str2,map,marks);
String LCS=getLCS(str1,str2,marks);
System.out.println("LCS = "+LCS);
System.out.println("result = "+result);
System.out.println("done");
}
}