**Example: * * given two sequences, for example X = ABCBDAB, Y = BDCABA, find the length of their longest common subsequence.
Subsequence: in the given two parent sequences, for example, sequence BCAB has appeared in the parent string ABCBDAB and BDCABA, and the order of occurrence is consistent with the parent string, which we call common subsequence. The longest common subsequence (LCS), as the name implies, refers to the longest one among all subsequences. In the example above, the longest common subsequence is BCAB.
Solving algorithm
There are n elements in the X string and m elements in the Y string
1. Violent solution
Assuming m < n, for the parent string Y, we can brutally find out the M-power subsequence of 2, and then match in the parent string X in turn, the time complexity of the algorithm will reach the exponential level o (m times of n * 2). Obviously, violent solution is not suitable for such problems.
2. Recursive method
The idea of recursion is to directly solve the next position when the corresponding position characters of array X and Y are the same, and take the larger value in two cases when they are not the same.
The code is as follows:
public class Longest common subsequence { public static int lcs(char[] x, char[] y, int i, int j) { if (i == 0 || j == 0) return 0; else if (x[i] == y[j]) return lcs(x, y, i - 1, j - 1) + 1; return max(lcs(x, y, i - 1, j), lcs(x, y, i, j - 1)); } private static int max(int a, int b) { if (a > b) return a; return b; } public static void main(String[] args) { String s1 = "ABCBDAB"; char[] c1 = new char[s1.length() + 1];// Character array with character 0 char[] t1 = s1.toCharArray(); c1[0] = (char)0; for(int i = 0; i < t1.length; i++) { c1[i + 1] = t1[i]; } String s2 = "BDCABA"; char[] c2 = new char[s2.length() + 1]; //Character array with 0 char[] t2 = s2.toCharArray(); c1[0] = (char)0; for(int i = 0; i < t2.length; i++) { c2[i + 1] = t2[i]; } System.err.println(lcs(c1, c2,c1.length - 1, c2.length - 1)); } }
The advantage of recursion is that it is easy to program and understand. The disadvantage is that the efficiency is not high, there are a large number of repeated recursive calls, increasing the complexity of time and space.
3. Dynamic planning
Memorandum act
Dynamic programming uses two-dimensional array to identify the intermediate calculation results, avoiding repeated calculation to improve efficiency.
public class Longest common subsequence { public static int lcs(char[] x, char[] y, int i, int j, int[][] bak) { if (bak[i][j] != -1) return bak[i][j]; if (i == 0 || j == 0) bak[i][j] = 0; if (i == 0 || j == 0) return 0; else if (x[i] == y[j]) bak[i][j] = lcs(x, y, i - 1, j - 1, bak) + 1; else bak[i][j] = max(lcs(x, y, i - 1, j, bak), lcs(x, y, i, j - 1, bak)); return bak[i][j]; } private static int max(int a, int b) { if (a > b) return a; return b; } public static void main(String[] args) { String s1 = "ABCBDAB"; char[] c1 = new char[s1.length() + 1];// Character array with character 0 char[] t1 = s1.toCharArray(); c1[0] = (char) 0; for (int i = 0; i < t1.length; i++) { c1[i + 1] = t1[i]; } String s2 = "BDCABA"; char[] c2 = new char[s2.length() + 1]; // Character array with 0 char[] t2 = s2.toCharArray(); c1[0] = (char) 0; for (int i = 0; i < t2.length; i++) { c2[i + 1] = t2[i]; } int[][] bak = new int[c1.length][c2.length]; for (int i = 0; i < c1.length; i++) { for (int j = 0; j < c2.length; j++) { bak[i][j] = -1; } } System.err.println(lcs(c1, c2, c1.length - 1, c2.length - 1, bak)); } }