示例#1
0
文件: Differ.cs 项目: Aiikon/TextDiff
        private static void BuildModificationData
            (ModificationData A,
            int startA,
            int endA,
            ModificationData B,
            int startB,
            int endB,
            int[] forwardDiagonal,
            int[] reverseDiagonal)
        {
            while (startA < endA && startB < endB && A.HashedPieces[startA].Equals(B.HashedPieces[startB]))
            {
                startA++;
                startB++;
            }
            while (startA < endA && startB < endB && A.HashedPieces[endA - 1].Equals(B.HashedPieces[endB - 1]))
            {
                endA--;
                endB--;
            }

            int aLength = endA - startA;
            int bLength = endB - startB;

            if (aLength > 0 && bLength > 0)
            {
                EditLengthResult res = CalculateEditLength(A.HashedPieces, startA, endA, B.HashedPieces, startB, endB, forwardDiagonal, reverseDiagonal);
                if (res.EditLength <= 0)
                {
                    return;
                }

                if (res.LastEdit == Edit.DeleteRight && res.StartX - 1 > startA)
                {
                    A.Modifications[--res.StartX] = true;
                }
                else if (res.LastEdit == Edit.InsertDown && res.StartY - 1 > startB)
                {
                    B.Modifications[--res.StartY] = true;
                }
                else if (res.LastEdit == Edit.DeleteLeft && res.EndX < endA)
                {
                    A.Modifications[res.EndX++] = true;
                }
                else if (res.LastEdit == Edit.InsertUp && res.EndY < endB)
                {
                    B.Modifications[res.EndY++] = true;
                }

                BuildModificationData(A, startA, res.StartX, B, startB, res.StartY, forwardDiagonal, reverseDiagonal);

                BuildModificationData(A, res.EndX, endA, B, res.EndY, endB, forwardDiagonal, reverseDiagonal);
            }
            else if (aLength > 0)
            {
                for (int i = startA; i < endA; i++)
                {
                    A.Modifications[i] = true;
                }
            }
            else if (bLength > 0)
            {
                for (int i = startB; i < endB; i++)
                {
                    B.Modifications[i] = true;
                }
            }
        }
示例#2
0
文件: Differ.cs 项目: zszqwe/dp2
        private static EditLengthResult CalculateEditLength(int[] A, int startA, int endA, int[] B, int startB, int endB, int[] forwardDiagonal, int[] reverseDiagonal)
        {
            if (null == A)
            {
                throw new ArgumentNullException("A");
            }
            if (null == B)
            {
                throw new ArgumentNullException("B");
            }

            if (A.Length == 0 && B.Length == 0)
            {
                return(new EditLengthResult());
            }

            Edit lastEdit;
            int  N         = endA - startA;
            int  M         = endB - startB;
            int  MAX       = M + N + 1;
            int  HALF      = MAX / 2;
            int  delta     = N - M;
            bool deltaEven = delta % 2 == 0;

            forwardDiagonal[1 + HALF] = 0;
            reverseDiagonal[1 + HALF] = N + 1;

            Log.WriteLine("Comparing strings");
            Log.WriteLine("\t{0} of length {1}", A, A.Length);
            Log.WriteLine("\t{0} of length {1}", B, B.Length);

            for (int D = 0; D <= HALF; D++)
            {
                Log.WriteLine("\nSearching for a {0}-Path", D);
                // forward D-path
                Log.WriteLine("\tSearching for foward path");
                for (int k = -D; k <= D; k += 2)
                {
                    Log.WriteLine("\n\t\tSearching diagonal {0}", k);
                    int kIndex = k + HALF;
                    int x, y;
                    if (k == -D || (k != D && forwardDiagonal[kIndex - 1] < forwardDiagonal[kIndex + 1]))
                    {
                        x        = forwardDiagonal[kIndex + 1]; // y up    move down from previous diagonal
                        lastEdit = Edit.InsertDown;
                        Log.Write("\t\tMoved down from diagonal {0} at ({1},{2}) to ", k + 1, x, (x - (k + 1)));
                    }
                    else
                    {
                        x        = forwardDiagonal[kIndex - 1] + 1; // x up     move right from previous diagonal
                        lastEdit = Edit.DeleteRight;
                        Log.Write("\t\tMoved right from diagonal {0} at ({1},{2}) to ", k - 1, x - 1, (x - 1 - (k - 1)));
                    }
                    y = x - k;
                    int startX = x;
                    int startY = y;
                    Log.WriteLine("({0},{1})", x, y);
                    while (x < N && y < M && A[x + startA] == B[y + startB])
                    {
                        x += 1;
                        y += 1;
                    }
                    Log.WriteLine("\t\tFollowed snake to ({0},{1})", x, y);

                    forwardDiagonal[kIndex] = x;

                    if (!deltaEven)
                    {
                        int revX, revY;
                        if (k - delta >= (-D + 1) && k - delta <= (D - 1))
                        {
                            int revKIndex = (k - delta) + HALF;
                            revX = reverseDiagonal[revKIndex];
                            revY = revX - k;
                            if (revX <= x && revY <= y)
                            {
                                var res = new EditLengthResult();
                                res.EditLength = 2 * D - 1;
                                res.StartX     = startX + startA;
                                res.StartY     = startY + startB;
                                res.EndX       = x + startA;
                                res.EndY       = y + startB;
                                res.LastEdit   = lastEdit;
                                return(res);
                            }
                        }
                    }
                }

                // reverse D-path
                Log.WriteLine("\n\tSearching for a reverse path");
                for (int k = -D; k <= D; k += 2)
                {
                    Log.WriteLine("\n\t\tSearching diagonal {0} ({1})", k, k + delta);
                    int kIndex = k + HALF;
                    int x, y;
                    if (k == -D || (k != D && reverseDiagonal[kIndex + 1] <= reverseDiagonal[kIndex - 1]))
                    {
                        x        = reverseDiagonal[kIndex + 1] - 1; // move left from k+1 diagonal
                        lastEdit = Edit.DeleteLeft;
                        Log.Write("\t\tMoved left from diagonal {0} at ({1},{2}) to ", k + 1, x + 1, ((x + 1) - (k + 1 + delta)));
                    }
                    else
                    {
                        x        = reverseDiagonal[kIndex - 1]; //move up from k-1 diagonal
                        lastEdit = Edit.InsertUp;
                        Log.Write("\t\tMoved up from diagonal {0} at ({1},{2}) to ", k - 1, x, (x - (k - 1 + delta)));
                    }
                    y = x - (k + delta);

                    int endX = x;
                    int endY = y;

                    Log.WriteLine("({0},{1})", x, y);
                    while (x > 0 && y > 0 && A[startA + x - 1] == B[startB + y - 1])
                    {
                        x -= 1;
                        y -= 1;
                    }

                    Log.WriteLine("\t\tFollowed snake to ({0},{1})", x, y);
                    reverseDiagonal[kIndex] = x;

                    if (deltaEven)
                    {
                        int forX, forY;
                        if (k + delta >= -D && k + delta <= D)
                        {
                            int forKIndex = (k + delta) + HALF;
                            forX = forwardDiagonal[forKIndex];
                            forY = forX - (k + delta);
                            if (forX >= x && forY >= y)
                            {
                                var res = new EditLengthResult();
                                res.EditLength = 2 * D;
                                res.StartX     = x + startA;
                                res.StartY     = y + startB;
                                res.EndX       = endX + startA;
                                res.EndY       = endY + startB;
                                res.LastEdit   = lastEdit;
                                return(res);
                            }
                        }
                    }
                }
            }


            throw new Exception("Should never get here");
        }