| 186 | } |
| 187 | |
| 188 | @SuppressWarnings("unchecked") public static DiffResult diff(String[] lhsString, String[] rhsString) { |
| 189 | DiffResult diffResult = new DiffResult(lhsString, rhsString); |
| 190 | int[] lhsHash = hash(lhsString); |
| 191 | int[] rhsHash = hash(rhsString); |
| 192 | int lhsLength = lhsHash.length; // number of lines of first file |
| 193 | int rhsLength = rhsHash.length; // number of lines of second file |
| 194 | |
| 195 | // opt[i][j] = length of LCS of x[i..M] and y[j..N] |
| 196 | int[][] opt = new int[lhsLength + 1][rhsLength + 1]; |
| 197 | List<Point>[][] flags = new ArrayList[lhsLength + 1][rhsLength + 1]; |
| 198 | |
| 199 | // compute length of LCS and all subproblems via dynamic programming |
| 200 | for (int i = 0; i < lhsLength; i++) { |
| 201 | for (int j = 0; j < rhsLength; j++) { |
| 202 | if (lhsHash[i] == rhsHash[j]) { |
| 203 | // We are the same so continue the diagonal is intact |
| 204 | if (i == 0 || j == 0) { |
| 205 | opt[i][j] = 0; |
| 206 | } else { |
| 207 | opt[i][j] = opt[i - 1][j - 1] + 1; |
| 208 | } |
| 209 | costDiag(flags, i, j); |
| 210 | } else { |
| 211 | cleanIslands(flags, i, j); |
| 212 | if (i == 0 || j == 0) { |
| 213 | opt[i][j] = 0; |
| 214 | } else { |
| 215 | opt[i][j] = Math.max(opt[i - 1][j], opt[i][j - 1]); |
| 216 | } |
| 217 | } |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | // recover LCS itself and print out non-matching lines to standard output |
| 222 | int i = 0, j = 0; |
| 223 | while (i < lhsLength && j < rhsLength) { |
| 224 | // if the diagonal is in tact walk it |
| 225 | if (lhsHash[i] == rhsHash[j]) { |
| 226 | diffResult.add(DiffResult.TYPE.SAME, i, j); |
| 227 | i++; |
| 228 | j++; |
| 229 | } |
| 230 | // otherwise walk along the xx or y axis which is the longer |
| 231 | // this is not always the best approach. |
| 232 | // we need to find the shortest path between {i,j} and the {i+ii,j+jj} which |
| 233 | // connects us to the next diagonal run |
| 234 | else if (opt[i + 1][j] >= opt[i][j + 1]) { |
| 235 | diffResult.add(DiffResult.TYPE.LEFT, i, j); |
| 236 | System.out.println("lhs:" + i + "< " + lhsString[i++]); |
| 237 | } else { |
| 238 | diffResult.add(DiffResult.TYPE.RIGHT, i, j); |
| 239 | System.out.println("rhs:" + j + "> " + rhsString[j++]); |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | // dump out one remainder of one string if the other is exhausted |
| 244 | while (i < lhsLength || j < rhsLength) { |
| 245 | if (i == lhsLength) { |