V[ 1 ] = 0;
for ( int d = 0 ; d <= N + M ; d++ )
{
for ( int k = -d ; k <= d ; k += 2 )
{
// down or right?
bool down = ( k == -d || ( k != d && V[ k - 1 ] < V[ k + 1 ] ) );
int kPrev = down ? k + 1 : k - 1;
// start point
int xStart = V[ kPrev ];
int yStart = xStart - kPrev;
// mid point
int xMid = down ? xStart : xStart + 1;
int yMid = xMid - k;
// end point
int xEnd = xMid;
int yEnd = yMid;
// follow diagonal
int snake = 0;
while ( xEnd < N && yEnd < M && A[ xEnd ] == B[ yEnd ] ) { xEnd++; yEnd++; snake++; }
// save end point
V[ k ] = xEnd;
// check for solution
if ( xEnd >= N && yEnd >= M ) /* solution has been found */
}
}
複製代碼
List<int[]> Vs; // saved V's indexed on d List<Snake> snakes; // list to hold solution Point p = new Point(n, n); // start at the end for ( int d = vs.Count - 1 ; p.X > 0 || p.Y > 0 ; d-- ) { int[] V = Vs[d]; int k = p.X - p.Y; // end point is in V int xEnd = V[k]; int yEnd = x - k; // down or right? bool down = ( k == -d || ( k != d && V[ k - 1 ] < V[ k + 1 ] ) ); int kPrev = down ? k + 1 : k - 1; // start point int xStart = V[ kPrev ]; int yStart = xStart - kPrev; // mid point int xMid = down ? xStart : xStart + 1; int yMid = xMid - k; snakes.Insert( 0, new Snake( /* start, mid and end points */ ) ); p.X = xStart; p.Y = yStart; } 複製代碼
Investigating Myers' diff algorithm: Part 1 of 2文章是用C#寫的,我這裏將它簡單改寫稱爲Java。 爲何這裏會倒着來遍歷,也就是說,爲何從最後一條snake遍歷到第一條snake呢?最後一條snake確定是咱們想要的有效路徑的必經之路,因此倒着來尋找snake,確定是找到的snake都是在有效路徑上,由於Vs數組裏面還有其餘狀況下的snake。
private void findMatchingItems() {
int posOld = mOldListSize;
int posNew = mNewListSize;
// traverse the matrix from right bottom to 0,0.
for (int i = mSnakes.size() - 1; i >= 0; i--) {
final Snake snake = mSnakes.get(i);
final int endX = snake.x + snake.size;
final int endY = snake.y + snake.size;
if (mDetectMoves) {
while (posOld > endX) {
// this is a removal. Check remaining snakes to see if this was added before
findAddition(posOld, posNew, i);
posOld--;
}
while (posNew > endY) {
// this is an addition. Check remaining snakes to see if this was removed
// before
findRemoval(posOld, posNew, i);
posNew--;
}
}
for (int j = 0; j < snake.size; j++) {
// matching items. Check if it is changed or not
final int oldItemPos = snake.x + j;
final int newItemPos = snake.y + j;
final boolean theSame = mCallback
.areContentsTheSame(oldItemPos, newItemPos);
final int changeFlag = theSame ? FLAG_NOT_CHANGED : FLAG_CHANGED;
mOldItemStatuses[oldItemPos] = (newItemPos << FLAG_OFFSET) | changeFlag;
mNewItemStatuses[newItemPos] = (oldItemPos << FLAG_OFFSET) | changeFlag;
}
posOld = snake.x;
posNew = snake.y;
}
}
複製代碼
public void dispatchUpdatesTo(ListUpdateCallback updateCallback) {
final BatchingListUpdateCallback batchingCallback;
if (updateCallback instanceof BatchingListUpdateCallback) {
batchingCallback = (BatchingListUpdateCallback) updateCallback;
} else {
batchingCallback = new BatchingListUpdateCallback(updateCallback);
// replace updateCallback with a batching callback and override references to
// updateCallback so that we don't call it directly by mistake //noinspection UnusedAssignment updateCallback = batchingCallback; } // These are add/remove ops that are converted to moves. We track their positions until // their respective update operations are processed. final List<PostponedUpdate> postponedUpdates = new ArrayList<>(); int posOld = mOldListSize; int posNew = mNewListSize; for (int snakeIndex = mSnakes.size() - 1; snakeIndex >= 0; snakeIndex--) { final Snake snake = mSnakes.get(snakeIndex); final int snakeSize = snake.size; final int endX = snake.x + snakeSize; final int endY = snake.y + snakeSize; if (endX < posOld) { dispatchRemovals(postponedUpdates, batchingCallback, endX, posOld - endX, endX); } if (endY < posNew) { dispatchAdditions(postponedUpdates, batchingCallback, endX, posNew - endY, endY); } for (int i = snakeSize - 1; i >= 0; i--) { if ((mOldItemStatuses[snake.x + i] & FLAG_MASK) == FLAG_CHANGED) { batchingCallback.onChanged(snake.x + i, 1, mCallback.getChangePayload(snake.x + i, snake.y + i)); } } posOld = snake.x; posNew = snake.y; } batchingCallback.dispatchLastEvent(); } 複製代碼