private void Diff(DiffDocument r, DiffDocument c, int i, int j) { if (i > 0 && j > 0 && r[i] == c[j]) { Diff(r, c, i - 1, j - 1); } else { if (j > 0 && (i == 0 || table[i][j - 1] >= table[i - 1][j])) { Diff(r, c, i, j - 1); if (lastChange == null || lastChange.Type != ChangeType.Add) { if (lastChange != null) { changeList.Add(lastChange); } lastChange = new Change() { Type = ChangeType.Add, StartPosition1 = i, StartPosition2 = j }; } lastChange.TextAdded += c[j] + Environment.NewLine; } else if (i > 0 && (j == 0 || table[i][j - 1] < table[i - 1][j])) { Diff(r, c, i - 1, j); if (lastChange == null || lastChange.Type != ChangeType.Remove) { if (lastChange != null) { changeList.Add(lastChange); } lastChange = new Change() { Type = ChangeType.Remove, StartPosition1 = i, StartPosition2 = j }; } lastChange.TextDeleted += r[i] + Environment.NewLine; } if (lastChange != null) { lastChange.EndPosition1 = i; lastChange.EndPosition2 = j; } } }
public DiffDocument Substring(int start, int end) { DiffDocument ret = new DiffDocument(); ret.Lines = new string[end - start]; for (int i = start; i < end; i++) { ret.Lines[i] = Lines[i]; } return ret; }
public List<Change> Diff(DiffDocument d1, DiffDocument d2) { table = new string[d1.Length][]; for (int i = 0; i < d1.Length; i++) { table[i] = new string[d2.Length]; } FindLcs(d1, d2); Diff(d1, d2, d1.Length - 1, d2.Length - 1); if (lastChange != null) { changeList.Add(lastChange); } table = null; return changeList; }
/// <summary> /// Find the longest common subsequence of lines across two documents. /// </summary> /// <param name="d1">The original document.</param> /// <param name="d2">The new document.</param> /// <returns>A string containing the longest common subsequence of identical lines across two documents</returns> private int FindLcs(DiffDocument d1, DiffDocument d2) { if (d2.Length <= 1 || d1.Length <= 1) return 0; if (table[d1.Length - 1][d2.Length - 1] != -1) { return table[d1.Length - 1][d2.Length - 1]; } int lcs; if (d1[d1.Length - 1] == (d2[d2.Length - 1])) { // Suppose that two sequences both end in the same element. To find their LCS, shorten each sequence by removing the last element, // find the LCS of the shortened sequences, and to that LCS append the removed element. lcs = FindLcs(d1.Substring(0, d1.Length - 2), d2.Substring(0, d2.Length - 2)) + 1; } else { // Suppose that the two sequences X and Y do not end in the same symbol. Then the LCS of X and Y is the longest sequence of LCS(Xn,Ym-1) and LCS(Xn-1,Ym). lcs = Math.Max(FindLcs(d1, d2.Substring(0, d2.Length - 2)), FindLcs(d1.Substring(0, d1.Length - 2), d2)); } table[d1.Length - 1][d2.Length - 1] = lcs; return lcs; }
static void Main(string[] args) { string s1 = @" This part of the document has stayed the same from version to version. It shouldn't be shown if it doesn't change. Otherwise, that would not be helping to compress the size of the changes. This paragraph contains text that is outdated. It will be deleted in the near future. It is important to spell check this dokument. On the other hand, a misspelled word isn't the end of the world. Nothing in the rest of this paragraph needs to be changed. Things can be added after it."; string s2 = @" This is an important notice! It should therefore be located at the beginning of this document! This part of the document has stayed the same from version to version. It shouldn't be shown if it doesn't change. Otherwise, that would not be helping to compress anything. It is important to spell check this document. On the other hand, a misspelled word isn't the end of the world. Nothing in the rest of this paragraph needs to be changed. Things can be added after it. This paragraph contains important new additions to this document."; string[] a = new string[] {@" a b d e" }; string[] b = new string[] {@" a f c d" }; string[] resultAb = new string[] { @"2a3 > c" }; string[] resultBa = new string[] { @"3d2 < c" }; DiffDocument d1 = new DiffDocument(a[0]); DiffDocument d2 = new DiffDocument(b[0]); Console.WriteLine("new Lcs().PrintDiff(d1, d2);"); foreach (Change c in new Lcs().Diff(d1, d2)) { Console.WriteLine(c); } Console.WriteLine("new Lcs().PrintDiff(d2, d1);"); foreach (Change c in new Lcs().Diff(d2, d1)) { Console.WriteLine(c); } Console.ReadKey(); }