Вопрос

Учитывая последовательность действий:

а*б*а*б*а*а*б*а*б

Есть ли способ получить оптимальное подразделение, позволяющее повторное использование подстроки.

изготовление

a*b*a*b*a*a*b*a*b => c*a*c, где c = a*b*a*b

а потом увидев это

a*b*a*b => d*d, где d = a*b

в итоге сократить 8 первоначальных операций до 4, описанных здесь?

(c = (d = a*b)*d)*a*c

Целью, конечно, является минимизация количества операций.

Я рассматриваю своего рода суффиксное дерево.

Меня особенно интересуют эвристики и решения линейного времени.Операции '*' на самом деле являются умножением матриц.

Это было полезно?

Решение

Эта вся эта проблема известна как «Общее преобразование подсудимости» или CSE . Это немного меньшей версию проблемы под названием « Уменьшение графика », с которыми сталкивается исполнитель Компиляторы для функциональных языков программирования. Googling «Общее алгоритм элиминации подпункции» дает множество решений, хотя, что я не вижу особенно для ограничения, заданных Matrix умножением.

Страницы, связанные с тем, чтобы дать много ссылок.

Мой старый ответ ниже. Тем не менее, изучав немного больше, решение просто строит Дерево суффикса . Это можно сделать в O (N) времени (много ссылок на странице Википедии). Сделав это, подсистемы (C, D и т. Д. В ваш вопрос) являются только узлами в дереве суффикса - просто вытащите их.


Тем не менее, я думаю, что Marcos на чем-то с предложением Допустимая повторяющаяся подстрока , как Приоритет снижения графика может не разрешить оптимизации, которые можно допустить здесь.

Эскиз алгоритма:

optimise(s):
    let sub = longestRepeatingSubstring(s).
    optimisedSub = optimise(sub)
    return s with sub replaced by optimisedSub
.

Каждый пробег из самой длинной повторяющейся подстроки требует времени N. Вы, вероятно, можете повторно использовать Дерево суффикс Вы построите, чтобы решить все это вовремя n.

Другие советы

Редактировать: Заказы на рост этого ответа необходимо в дополнение к принятому ответу, чтобы запустить CSE или Matrix-цепочку умножения

Интересно, что алгоритм сжатия может быть то, что вы хотите: алгоритм сжатия стремится уменьшить размер того, что он сжимается, и если единственный способ сделать это подстановку, вы можете проследить его и получить необходимые подкомпоненты для вашего алгоритм. Это может не дать приятных результатах, хотя для небольших входов.

Какие подмножества ваших операций являются коммутативным соображением, будет важным соображением при выборе такого алгоритма. [Редактировать: OP говорит, что нет операций, не являются коммутативными в его / ее ситуации]

Мы также можем определить оптимальное решение, если мы игнорируем эффекты, такие как кеширование:

input: [some product of matrices to compute]

given that multiplying two NxN matrices is O(N^2.376)
given we can visualize the product as follows:
    [[AxB][BxC][CxD][DxE]...]
we must for example perform O(max(A,B,C)^2.376) or so operations in order to combine
    [AxB][BxC] -> [AxC]

The max(...) is an estimate based on how fast it is to multiply two square matrices;
a better estimate of cost(A,B,C) for multiplying an AxB * BxC matrix can be gotten 
from actually looking at the algorithm, or running benchmarks if you don't know the
algorithm used.

However note that multiplying the same matrix with itself, i.e. calculating
a power, can be much more efficient, and we also need to take that into account.
At worst, it takes log_2(power) multiplies each of O(N^2.376), but this could be
made more efficient by diagonalizing the matrix first.
.

Есть вопрос о том, является ли жадный подход для не: то, следует ли сжать повторяющиеся подстроки на каждом шаге. Это может быть не так, например.

aaaaabaab
compressing 'aa' results in ccabcb and compressing 'aab' is now impossible
.

Однако у меня есть догадка, что, если мы попробуем все заказы сжимающихся подстроки, мы, вероятно, не будем запускать эту проблему слишком часто. Таким образом, записав то, что мы хотим (затраты) и считают, возможно, проблемы, у нас уже есть алгоритм грубого силы, который может сделать это, и он будет работать на очень небольшое количество матриц:

# pseudocode

def compress(problem, substring)
    x = new Problem(problem)
    x.string.replaceall(substring, newsymbol)
    x.subcomputations += Subcomputation(newsymbol=substring)

def bestCompression(problem)
    candidateCompressions = [compress(problem,substring) for each substring in problem.string]
    # etc., recursively return problem with minimum cost
    # dynamic programming may help make this more efficient, but one must watch
    #   out for the note above, how it may be hard to be greedy
.

Примечание: в соответствии с другим ответом Asgeir, это известно как проблема оптимизации умножения цепочки матрицы. Nick ForeScue Notes Это также известно, как правило, как http://en.wikipedia.org/wiki/common_subexpression_elimination< a> - Таким образом, можно найти любой универсальный алгоритм / библиотека умножения CSE или MATRIX или MATRIX и MATRIX, а подключаю к затратам затрат на величину, я упомянул ранее (вам понадобится эти точке Какое решение вы используете). Обратите внимание, что стоимость вышеуказанных расчетов (умножение, экспоненция и т. Д.) предполагает, что они делаются эффективно с современными алгоритмами; Если это не так, замените показатели соответствующими значениями, которые соответствуют проведению операций.

Если вы хотите использовать наименьшее количество арифметических операций, то вам следует посмотреть на Matrix Chyth умножения Что может быть уменьшено до O (n log n)

С самого начала мне кажется, что проблема в NP.В зависимости от замен, которые вы выполняете, другие замены будут возможны или невозможны, например, для строкиd*e*a*b*c*d*e*a*b*c*d*e*a есть несколько возможностей.

Если вы возьмете самую длинную общую строку, это будет:f = d*e*a*b*c и вы могли бы заменить f*f*e*a оставив вам три умножения в конце и четыре промежуточных (всего семь).

Если вместо этого вы замените следующим образом:f = d*e*a Вы получаете f*b*c*f*b*c*f который вы можете дополнительно заменить, используя g = f*b*c кg*g*f всего шесть умножений.

В этой задаче возможны и другие замены, но сейчас у меня нет времени их все перечислять.

Я предполагаю, что для полной минимальной замены необходимо не только определить самую длинную общую подстроку, но и количество повторений каждой подстроки, что, вероятно, означает, что вам придется отслеживать все замены на данный момент и выполнять обратный поиск.Тем не менее, это может быть быстрее, чем фактическое умножение.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top