Изучение разностного алгоритма Майерса: часть 2 - Средняя змея

ОГЛАВЛЕНИЕ

Средняя змея

Совпадение

Можно одновременно прогнать прямой и обратный алгоритмы для последовательных значений D. При каком-то значении D две змеи совпадут на какой-то k линии. Статья доказывает, что одна из этих змей является частью решения. Так как она будет находиться где-то посередине, она называется средней змеей.

Средняя змея для примера выделена розовым  на этой диаграмме:

Рисунок 2: Средняя змея

Средняя змея полезна, потому что делит задачу на две части, которые затем можно решить отдельно и рекурсивно.

Средняя змея линейна в пространстве, потому что только последние V векторов должны храниться, давая O (D). Пока этот линейный алгоритм все еще является O ((N+M) D).

Помогает то, что средняя змея должна быть найдена с D, равным половине D из прямого и обратного алгоритмов. Отсюда следует, что по мере того как D возрастает, требуемое время достигает половины времени, требуемого базовым алгоритмам.

Ниже приведен имеющийся пока псевдокод:

for d = 0 to ( N + M + 1 ) / 2
{
  for k = -d to d step 2
  {
    вычислить самый дальний прямой и обратный пути достижения
    если есть совпадение, имеем среднюю змею
  }
}

Нечетная и четная дельты

Каждая разность – горизонтальное удаление или вертикальная вставка – является сдвигом от одной k линии к ее соседней линии. Поскольку дельта является разностью между серединами прямого и обратного алгоритмов, известно, какие значения d надо проверять на среднюю змею.

Для нечетной дельты надо искать совпадение прямых путей с разностями d и обратных путей с разностями d - 1.

Эта диаграмма показывает, что для дельты = 3 совпадение происходит, когда прямая d равна 2 и обратная d равна 1:

Рисунок 3: Нечетная дельта

Аналогично для четной дельты совпадения будут, когда прямой и обратный пути имеют одинаковое число разностей.

Следующая диаграмма показывает, что для дельта = 2 совпадение происходит, когда прямая и обратная разности равны 2:

Рисунок 4: Четная дельта

Алгоритм

Ниже приведен полный псевдокод для отыскания средней змеи:

delta = N - M
for d = 0 to ( N + M + 1 ) / 2
{
  for k = -d to d step 2
  {
    вычислить самый дальний прямой путь достижения на линии k
    если delta нечетна и ( k >= delta - ( d - 1 ) и k <= delta + ( d - 1 ) )
      если совпадение с обратным [ d - 1 ] на линии k
        => найдена средняя змея и SES длины 2D - 1
  }
 
  for k = -d to d step 2
  {
    вычислить самый дальний обратный путь достижения на линии k
    если дельта четна и (k >= -d - delta и k <= d - delta)
      если совпадение с прямым [ d ] на линии k
        => найдена средняя змея и SES длины 2D
  }
}

Замечание: Граничные проверки k служат для исключения невозможных совпадений.