package ilarkesto.core.diff; import java.util.Arrays; import java.util.LinkedList; import java.util.List; public class LongestCommonSubsequenceList { // These are "constants" which indicate a direction in the backtracking array. private static final int NEITHER = 0; private static final int UP = 1; private static final int LEFT = 2; private static final int UP_AND_LEFT = 3; public static List<String> execute(List<String> a, List<String> b) { int n = a.size(); int m = b.size(); int S[][] = new int[n + 1][m + 1]; int R[][] = new int[n + 1][m + 1]; int ii, jj; // It is important to use <=, not <. The next two for-loops are initialization for (ii = 0; ii <= n; ++ii) { S[ii][0] = 0; R[ii][0] = UP; } for (jj = 0; jj <= m; ++jj) { S[0][jj] = 0; R[0][jj] = LEFT; } // This is the main dynamic programming loop that computes the score and // backtracking arrays. for (ii = 1; ii <= n; ++ii) { for (jj = 1; jj <= m; ++jj) { if (a.get(ii - 1).equals(b.get(jj - 1))) { S[ii][jj] = S[ii - 1][jj - 1] + 1; R[ii][jj] = UP_AND_LEFT; } else { S[ii][jj] = S[ii - 1][jj - 1] + 0; R[ii][jj] = NEITHER; } if (S[ii - 1][jj] >= S[ii][jj]) { S[ii][jj] = S[ii - 1][jj]; R[ii][jj] = UP; } if (S[ii][jj - 1] >= S[ii][jj]) { S[ii][jj] = S[ii][jj - 1]; R[ii][jj] = LEFT; } } } // The length of the longest substring is S[n][m] ii = n; jj = m; int pos = S[ii][jj] - 1; String[] lcs = new String[pos + 1]; // Trace the backtracking matrix. while (ii > 0 || jj > 0) { if (R[ii][jj] == UP_AND_LEFT) { ii--; jj--; lcs[pos--] = a.get(ii); } else if (R[ii][jj] == UP) { ii--; } else if (R[ii][jj] == LEFT) { jj--; } } return new LinkedList<String>(Arrays.asList(lcs)); } }