Подход, который я, вероятно, выбрал бы, будет выглядеть так:
Создайте массив ("X
") из (N+1)xM
элементов, где N
= "ширина" вашего 2D-массива и M
= количество символов в вашем списке.
Установите X[0][i] = 0
для всех значений i (в диапазоне M
). Это связано с тем, что максимально возможная сумма первых 0 выбранных элементов равна 0. Мы также можем заполнить X[a][b]
как 0 для любого b>=a
, поскольку эти позиции являются теми, к которым мы не смогли бы добраться (у нас не было бы выбрал достаточно символов, чтобы быть в этом символе еще). Точно так же мы можем установить «треугольник» значений в конце массива также на 0, так как для достижения одного из этих индексов нам нужно было бы выбрать слишком много повторений более ранних символов, чтобы иметь возможность выбрать хотя бы один элемент для более поздних символов.
Теперь установите X[1][i]
равным максимально возможной сумме первых 1 выбранных элементов, если текущий выбранный символ является символом i
в последовательности. Это довольно просто вычислить - это просто соответствующее значение для этого символа из массива.
Теперь установите X[2][i]
равным максимально возможной сумме первых 2 выбранных элементов, если текущий выбранный символ является символом i
в последовательности. Это также довольно тривиально, хотя и не так просто, как было [1] - в конце концов, теперь это соответствующее значение символа плюс максимум либо X[1][i-1]
, либо X[1][i]
- потому что мы могли либо начните текущий символ с этой позиции, либо уже начали с более ранней позиции.
Продолжайте алгоритм для каждого X[k]
(установка X[k][i]
равна максимальному из X[k-1][i-1]
или X[k-1][i]
, плюс соответствующее значение символа для текущего i
), пока k
не достигнет N
, Максимальное значение в вашем столбце X[k]
- ваш максимальный результат.
Поскольку в целом вам нужно только смотреть на каждый элемент массива постоянное число раз, общий алгоритм запускается за O(MN)
времени.
(Обратите внимание, что технически вам не нужен весь массив NxM в памяти все время, только предыдущий столбец и текущий столбец. Это проще объяснить в терминах полного массива. Таким образом, оптимизированная версия этого алгоритм использует O(M)
памяти.)
Пример массива результатов из вашего примера:
0 1 2 3 4 5 6 7 8 9 10 11 12 13
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0 - C | 0| 1| 2| 3| 6|10|13|22|23|24| 0| 0| 0| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1 - A | 0| 0| 2| 3| 7|10|13|17|24|26|27| 0| 0| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2 - B | 0| 0| 0| 7| 9|10|11|14|18|25|26|28| 0| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
3 - D | 0| 0| 0| 0|12|16|19|21|23|27|32|38|44| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
4 - C | 0| 0| 0| 0| 0|16|19|28|29|30|31|33|36|45|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Если вы сохраняете (в каждой позиции массива), какой предыдущий символ использовался как часть общей суммы этой позиции, то легко просто прочитать обратно путь, который ведет от нижнего правого угла к верхнему левому углу, чтобы выяснить, что такое максимальная последовательность Кроме того, вы можете просто проследить назад, посмотрев, какое из двух значений - левое или левое - больше вашей текущей позиции. В этом случае максимальная последовательность CABDDDDDDDDDC.