Exemple #1
0
        private void GetMatchPoints(SubArray A, SubArray B, ArrayList MatchPoints)
        {
            if (A.Length > 0 && B.Length > 0)
            {
                //Find the middle snake from (x,y) to (u,v)
                int x, u, k;
                int D = FindMiddleSnake(A, B, out x, out u, out k);
                int y = x - k;
                int v = u - k;

                if (D > 1)
                {
                    GetMatchPoints(new SubArray(A, 1, x), new SubArray(B, 1, y), MatchPoints);

                    for (int i = x + 1; i <= u; i++)
                    {
                        //Output absolute X and Y (not relative to the current subarray)
                        MatchPoints.Add(new Point(i + A.Offset, i - k + B.Offset));
                    }

                    GetMatchPoints(new SubArray(A, u + 1, A.Length - u), new SubArray(B, v + 1, B.Length - v), MatchPoints);
                }
                else
                {
                    //If there are no differences, we have to output all of the points.
                    //If there's only one difference, we have to output all of the
                    //match points, skipping the single point that is different.
                    Debug.Assert(D == 0 || Math.Abs(A.Length - B.Length) == 1, "A and B's lengths must differ by 1 if D == 1");

                    //Only go to the minimum of the two lengths since that's the
                    //most that can possibly match between the two subsequences.
                    int N = A.Length;
                    int M = B.Length;
                    if (M > N)
                    {
                        //Output A[1..N] as match points
                        int iCurrY = 1;
                        for (int i = 1; i <= N; i++)
                        {
                            //We must skip the one difference when we hit it
                            if (A[i] != B[iCurrY])
                            {
                                iCurrY++;
                            }

                            MatchPoints.Add(new Point(i + A.Offset, iCurrY + B.Offset));
                            iCurrY++;
                        }
                    }
                    else
                    {
                        //Output B[1..M] as match points
                        int iCurrX = 1;
                        for (int i = 1; i <= M; i++)
                        {
                            //We must skip the one difference when we hit it
                            if (A[iCurrX] != B[i])
                            {
                                iCurrX++;
                            }
                            MatchPoints.Add(new Point(iCurrX + A.Offset, i + B.Offset));
                            iCurrX++;
                        }
                    }
                }
            }
        }
Exemple #2
0
        private int FindMiddleSnake(SubArray A, SubArray B, out int iPathStartX, out int iPathEndX, out int iPathK)
        {
            //We don't have to check the result of this because the calling procedure
            //has already check the length preconditions.
            SetupFictitiousPoints(A, B);

            iPathStartX = -1;
            iPathEndX   = -1;
            iPathK      = 0;

            int iDelta   = A.Length - B.Length;
            int iCeiling = (int)Math.Ceiling((A.Length + B.Length) / 2.0);

            for (int D = 0; D <= iCeiling; D++)
            {
                for (int k = -D; k <= D; k += 2)
                {
                    //Find the end of the furthest reaching forward D-path in diagonal k.
                    GetForwardDPaths(A, B, D, k);
                    //If iDelta is odd (i.e. remainder == 1 or -1) and ...
                    if ((iDelta % 2 != 0) && (k >= (iDelta - (D - 1)) && k <= (iDelta + (D - 1))))
                    {
                        //If the path overlaps the furthest reaching reverse (D-1)-path in diagonal k.
                        if (m_vecForward[k] >= m_vecReverse[k])
                        {
                            //The last snake of the forward path is the middle snake.
                            iPathK      = k;
                            iPathEndX   = m_vecForward[k];
                            iPathStartX = iPathEndX;
                            int iPathStartY = iPathStartX - iPathK;
                            while (iPathStartX > 0 && iPathStartY > 0 && A[iPathStartX] == B[iPathStartY])
                            {
                                iPathStartX--;
                                iPathStartY--;
                            }
                            //Length of an SES is 2D-1.
                            return(2 * D - 1);
                        }
                    }
                }

                for (int k = -D; k <= D; k += 2)
                {
                    //Find the end of the furthest reaching reverse D=path in diagonal k+iDelta
                    GetReverseDPaths(A, B, D, k, iDelta);
                    //If iDelta is even and ...
                    if ((iDelta % 2 == 0) && ((k + iDelta) >= -D && (k + iDelta) <= D))
                    {
                        //If the path overlaps the furthest reaching forward D-path in diagonal k+iDelta.
                        if (m_vecReverse[k + iDelta] <= m_vecForward[k + iDelta])
                        {
                            //The last snake of the reverse path is the middle snake.
                            iPathK      = k + iDelta;
                            iPathStartX = m_vecReverse[iPathK];
                            iPathEndX   = iPathStartX;
                            int iPathEndY = iPathEndX - iPathK;
                            while (iPathEndX < A.Length && iPathEndY < B.Length && A[iPathEndX + 1] == B[iPathEndY + 1])
                            {
                                iPathEndX++;
                                iPathEndY++;
                            }
                            //Length of an SES is 2D.
                            return(2 * D);
                        }
                    }
                }
            }

            //We should never get here if the algorithm is coded correctly.
            Debug.Assert(false);
            return(-1);
        }