private void GetLongestSourceMatch(CompareState curItem, int destIndex, int destEnd, int sourceStart, int sourceEnd) { int maxDestLength = (destEnd - destIndex) + 1; int curBestLength = 0; int curBestIndex = -1; for (int sourceIndex = sourceStart; sourceIndex <= sourceEnd; sourceIndex++) { int maxLength = Math.Min(maxDestLength, (sourceEnd - sourceIndex) + 1); if (maxLength <= curBestLength) { //No chance to find a longer one any more break; } int curLength = GetSourceMatchLength(destIndex, sourceIndex, maxLength); if (curLength > curBestLength) { //This is the best match so far curBestIndex = sourceIndex; curBestLength = curLength; } //jump over the match sourceIndex += curBestLength; } //DiffState cur = _stateList.GetByIndex(destIndex); if (curBestIndex == -1) { curItem.SetNoMatch(); } else { curItem.SetMatch(curBestIndex, curBestLength); } }
//This is the actual recursive search that looks for longes common-subsequence private void RecursiveComparer(int destinationStart, int destinationEnd, int sourceStart, int sourceEnd) { int curBestIndex = -1; int curBestLength = -1; CompareState currentItem; CompareState bestItem = null; for (int count = destinationStart; count <= destinationEnd; count++) { int maxPossibleDestLength = (destinationEnd - count) + 1; if (maxPossibleDestLength <= curBestLength) { //not enough text remaining to be larger then the current best break; } currentItem = compareStateList.GetByIndex(count); if (!currentItem.HasValidLength(sourceStart, sourceEnd, maxPossibleDestLength)) { //recalc new best length since it isn't valid or has never been done. GetLongestSourceMatch(currentItem, count, destinationEnd, sourceStart, sourceEnd); } if (currentItem.Status == CompareStatus.Matched) { if (currentItem.Length > curBestLength) { //this is longest match so far curBestIndex = count; curBestLength = currentItem.Length; bestItem = currentItem; } break; } } if (curBestIndex < 0) { //we are done - there are no matches in this span } else { int sourceIndex = 0; if (bestItem != null) { sourceIndex = bestItem.StartIndex; } matchList.Add(CompareResultSpan.CreateNoChange(curBestIndex, sourceIndex, curBestLength)); if (destinationStart < curBestIndex) { //Still have more lower destination data if (sourceStart < sourceIndex) { //Still have more lower source data // Recursive call to process lower indexes RecursiveComparer(destinationStart, curBestIndex - 1, sourceStart, sourceIndex - 1); } } int upperDestStart = curBestIndex + curBestLength; int upperSourceStart = sourceIndex + curBestLength; if (destinationEnd > upperDestStart) { //we still have more upper dest data if (sourceEnd > upperSourceStart) { //set still have more upper source data // Recursive call to process upper indexes RecursiveComparer(upperDestStart, destinationEnd, upperSourceStart, sourceEnd); } } } }