给定两个字符串,求两个字符串的最大长共子序列,比如A1B45CD,12AB67C,所以这两个字符串的公共子字符串为ABC。注意公共子序列和公共子字符串区别。
求法分两步,第一步求出最长公共子序列的长度,第二步,根据最长长度回溯求出其中对应的子序列。
代码:
public class Main { //生成dp数组 public static int[][] getdp(char[] c1, char[] c2) { int len1 = c1.length; int len2 = c2.length; int[][] dp = new int[len1][len2]; dp[0][0]= c1[0]==c2[0] ? 1:0; //第一行填充 for(int j=1; j<len2; j++) { dp[0][j] = Math.max(dp[0][j-1], c1[0]==c2[j] ? 1 : 0); } //第一列填充 for(int i=1; i<len1; i++) { dp[i][0] = Math.max(dp[i-1][0], c1[i]==c2[0] ? 1 : 0); } for(int i=1; i<len1; i++) { for(int j=1; j<len2; j++) { dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]); if(c1[i] == c2[j]) { dp[i][j] = Math.max(dp[i][j], dp[i-1][j-1]+1); } } }return dp; } //最长公共子序列Longest Common Subsequence public static String lcs(String s1, String s2) { if(s1==null || s1.length()==0 || s2==null || s2.length()==0) { return null; } char[] c1 = s1.toCharArray(); char[] c2 = s2.toCharArray(); int[][] dp = getdp(c1, c2); int row = dp.length-1; int col = dp[0].length-1; int longestNum = dp[row][col]-1; char[] res = new char[dp[row][col]]; while(longestNum>=0) { if(row>0 && dp[row][col] == dp[row-1][col]) { row--; } else if(col>0 && dp[row][col] == dp[row][col-1]){ col--; } else { res[longestNum--] = c1[row]; row--; col--; } } return String.valueOf(res); } public static void main(String[] args) { String s1 = "1A2C3D4B56"; String s2 = "B1D23CA45B6A"; System.out.println(lcs(s1, s2)); } }