Example #1
0
    } // SMS


    /// <summary>
    /// This is the divide-and-conquer implementation of the longes common-subsequence (LCS) 
    /// algorithm.
    /// The published algorithm passes recursively parts of the A and B sequences.
    /// To avoid copying these arrays the lower and upper bounds are passed while the sequences stay constant.
    /// </summary>
    /// <param name="DataA">sequence A</param>
    /// <param name="LowerA">lower bound of the actual range in DataA</param>
    /// <param name="UpperA">upper bound of the actual range in DataA (exclusive)</param>
    /// <param name="DataB">sequence B</param>
    /// <param name="LowerB">lower bound of the actual range in DataB</param>
    /// <param name="UpperB">upper bound of the actual range in DataB (exclusive)</param>
    private static void LCS(DiffData DataA, int LowerA, int UpperA, DiffData DataB, int LowerB, int UpperB) {
      // Debug.Write(2, "LCS", String.Format("Analyse the box: A[{0}-{1}] to B[{2}-{3}]", LowerA, UpperA, LowerB, UpperB));

      // Fast walkthrough equal lines at the start
      while (LowerA < UpperA && LowerB < UpperB && DataA.data[LowerA] == DataB.data[LowerB]) {
        LowerA++; LowerB++;
      }

      // Fast walkthrough equal lines at the end
      while (LowerA < UpperA && LowerB < UpperB && DataA.data[UpperA-1] == DataB.data[UpperB-1]) {
        --UpperA; --UpperB;
      }
			
      if (LowerA == UpperA) {
        // mark as inserted lines.
        while (LowerB < UpperB)
          DataB.modified[LowerB++] = true;

      } else if (LowerB == UpperB) {
        // mark as deleted lines.
        while (LowerA < UpperA)
          DataA.modified[LowerA++] = true;

      } else {
        // Find the middle snakea and length of an optimal path for A and B
        SMSRD smsrd = SMS(DataA, LowerA, UpperA, DataB, LowerB, UpperB);
        // Debug.Write(2, "MiddleSnakeData", String.Format("{0},{1}", smsrd.x, smsrd.y));

        // The path is from LowerX to (x,y) and (x,y) ot UpperX
        LCS(DataA, LowerA, smsrd.x, DataB, LowerB, smsrd.y);
        LCS(DataA, smsrd.x, UpperA, DataB, smsrd.y, UpperB);  // 2002.09.20: no need for 2 points 
      }
    } // LCS()
Example #2
0
    private static void LCS(ref DiffData DataA, int LowerA, int UpperA, ref DiffData DataB, int LowerB, int UpperB, int[] DownVector, int[] UpVector)
    {
        // Fast walkthrough equal lines at the start
        while ((LowerA < UpperA && LowerB < UpperB && DataA.data[LowerA] == DataB.data[LowerB]))
        {
            LowerA += 1;
            LowerB += 1;
        }

        // Fast walkthrough equal lines at the end
        while ((LowerA < UpperA && LowerB < UpperB && DataA.data[UpperA - 1] == DataB.data[UpperB - 1]))
        {
            UpperA -= 1;
            UpperB -= 1;
        }

        if ((LowerA == UpperA))
        {
            // mark as inserted lines.
            while ((LowerB < UpperB))
            {
                //LowerB += 1
                DataB.modified[LowerB] = true;
                LowerB += 1;
            }
        }
        else if ((LowerB == UpperB))
        {
            // mark as deleted lines.
            while ((LowerA < UpperA))
            {
                //LowerA += 1
                DataA.modified[LowerA] = true;
                LowerA += 1;
            }
        }
        else
        {
            // Find the middle snakea and length of an optimal path for A and B
            SMSRD smsrd = SMS(ref DataA, LowerA, UpperA, ref DataB, LowerB, UpperB, DownVector, UpVector);
            // Debug.Write(2, "MiddleSnakeData", String.Format("{0},{1}", smsrd.x, smsrd.y));

            // The path is from LowerX to (x,y) and (x,y) to UpperX
            LCS(ref DataA, LowerA, smsrd.x, ref DataB, LowerB, smsrd.y, DownVector, UpVector);
            LCS(ref DataA, smsrd.x, UpperA, ref DataB, smsrd.y, UpperB, DownVector, UpVector);
            // 2002.09.20: no need for 2 points
        }
    }
Example #3
0
        // SMS

        /// <summary>
        /// This is the divide-and-conquer implementation of the longest common-subsequence (LCS)
        /// algorithm.
        /// The published algorithm passes recursively parts of the A and B sequences.
        /// To avoid copying these arrays the lower and upper bounds are passed while the sequences stay constant.
        /// </summary>
        /// <param name="dataA">sequence A</param>
        /// <param name="lowerA">lower bound of the actual range in DataA</param>
        /// <param name="upperA">upper bound of the actual range in DataA (exclusive)</param>
        /// <param name="dataB">sequence B</param>
        /// <param name="lowerB">lower bound of the actual range in DataB</param>
        /// <param name="upperB">upper bound of the actual range in DataB (exclusive)</param>
        /// <param name="downVector">a vector for the (0,0) to (x,y) search. Passed as a parameter for speed reasons.</param>
        /// <param name="upVector">a vector for the (u,v) to (N,M) search. Passed as a parameter for speed reasons.</param>
        static void LCS <T> (DiffData <T> dataA, int lowerA, int upperA, DiffData <T> dataB, int lowerB, int upperB, int[] downVector, int[] upVector)
        {
            // Fast walkthrough equal lines at the start
            while (lowerA < upperA && lowerB < upperB && dataA.Data[lowerA].Equals(dataB.Data[lowerB]))
            {
                lowerA++;
                lowerB++;
            }

            // Fast walkthrough equal lines at the end
            while (lowerA < upperA && lowerB < upperB && dataA.Data[upperA - 1].Equals(dataB.Data[upperB - 1]))
            {
                --upperA;
                --upperB;
            }

            if (lowerA == upperA)
            {
                // mark as inserted lines.
                while (lowerB < upperB)
                {
                    dataB.Modified[lowerB++] = true;
                }
            }
            else if (lowerB == upperB)
            {
                // mark as deleted lines.
                while (lowerA < upperA)
                {
                    dataA.Modified[lowerA++] = true;
                }
            }
            else
            {
                // Find the middle snakea and length of an optimal path for A and B
                SMSRD smsrd = SMS(dataA, lowerA, upperA, dataB, lowerB, upperB, downVector, upVector);
                // Debug.Write(2, "MiddleSnakeData", String.Format("{0},{1}", smsrd.x, smsrd.y));

                // The path is from LowerX to (x,y) and (x,y) to UpperX
                LCS(dataA, lowerA, smsrd.x, dataB, lowerB, smsrd.y, downVector, upVector);
                LCS(dataA, smsrd.x, upperA, dataB, smsrd.y, upperB, downVector, upVector);
                // 2002.09.20: no need for 2 points
            }
        }
Example #4
0
    private static SMSRD SMS(ref DiffData DataA, int LowerA, int UpperA, ref DiffData DataB, int LowerB, int UpperB, int[] DownVector, int[] UpVector)
    {
        SMSRD ret = new SMSRD();
        int   MAX = DataA.Length + DataB.Length + 1;

        int DownK = LowerA - LowerB;
        // the k-line to start the forward search
        int UpK = UpperA - UpperB;
        // the k-line to start the reverse search

        int  Delta    = (UpperA - LowerA) - (UpperB - LowerB);
        bool oddDelta = Delta == 1;

        // The vectors in the publication accepts negative indexes. the vectors implemented here are 0-based
        // and are access using a specific offset: UpOffset UpVector and DownOffset for DownVektor
        int DownOffset = MAX - DownK;
        int UpOffset   = MAX - UpK;

        int MaxD = ((UpperA - LowerA + UpperB - LowerB) / 2) + 1;

        //  Debug.Write(2, "SMS", String.Format("Search the box: A[{0}-{1}] to B[{2}-{3}]", LowerA, UpperA, LowerB, UpperB));

        // init vectors
        DownVector[DownOffset + DownK + 1] = LowerA;
        UpVector[UpOffset + UpK - 1]       = UpperA;


        for (int D = 0; D <= MaxD; D++)
        {
            // Extend the forward path.
            for (int k = DownK - D; k <= DownK + D; k += 2)
            {
                // Debug.Write(0, "SMS", "extend forward path " + k.ToString())

                // find the only or better starting point
                int x = 0;
                int y = 0;
                if ((k == DownK - D))
                {
                    x = DownVector[DownOffset + k + 1];
                    // down
                }
                else
                {
                    x = DownVector[DownOffset + k - 1] + 1;
                    // a step to the right
                    if (((k < DownK + D) && (DownVector[DownOffset + k + 1] >= x)))
                    {
                        x = DownVector[DownOffset + k + 1];
                        // down
                    }
                }
                y = x - k;

                // find the end of the furthest reaching forward D-path in diagonal k.
                while (((x < UpperA) && (y < UpperB) && (DataA.data[x] == DataB.data[y])))
                {
                    x = x + 1;
                    y = y + 1;
                }
                DownVector[DownOffset + k] = x;

                // overlap ?
                if ((oddDelta == true && (UpK - D < k) && (k < UpK + D)))
                {
                    if ((UpVector[UpOffset + k] <= DownVector[DownOffset + k]))
                    {
                        ret.x = DownVector[DownOffset + k];
                        ret.y = DownVector[DownOffset + k] - k;
                        // ret.u = UpVector(UpOffset + k);      // 2002.09.20: no need for 2 points
                        // ret.v = UpVector(UpOffset + k) - k;
                        return(ret);
                    }
                }
            }

            // Extend the reverse path.
            for (int k = UpK - D; k <= UpK + D; k += 2)
            {
                // Debug.Write(0, "SMS", "extend reverse path " + k.ToString());

                // find the only or better starting point
                int x = 0;
                int y = 0;
                if ((k == UpK + D))
                {
                    x = UpVector[UpOffset + k - 1];
                    // up
                }
                else
                {
                    x = UpVector[UpOffset + k + 1] - 1;
                    // left
                    if (((k > UpK - D) && (UpVector[UpOffset + k - 1] < x)))
                    {
                        x = UpVector[UpOffset + k - 1];
                        // up
                    }
                }
                y = x - k;

                while (((x > LowerA) && (y > LowerB) && (DataA.data[x - 1] == DataB.data[y - 1])))
                {
                    x = x - 1;
                    y = y - 1;
                    // diagonal
                }
                UpVector[UpOffset + k] = x;

                // overlap ?
                if ((oddDelta == false && (DownK - D <= k) && (k <= DownK + D)))
                {
                    if ((UpVector[UpOffset + k] <= DownVector[DownOffset + k]))
                    {
                        ret.x = DownVector[DownOffset + k];
                        ret.y = DownVector[DownOffset + k] - k;
                        // ret.u = UpVector(UpOffset + k)     ' 2002.09.20: no need for 2 points
                        // ret.v = UpVector(UpOffset + k) - k
                        return(ret);
                    }
                }
            }
        }

        throw new ApplicationException("the algorithm should never come here.");
    }