Учитывая две строки , мы пишем для их объединения. Учитывая , строка и целое число , мы будем писать для конкатенации копий . Теперь, учитывая строку, мы можем использовать эту запись, чтобы «сжать» ее, то есть можно записать как . Давайте называть вессжатиячисло символоввходящих в него, так что вес состоитдвух, а вес (скомпрессиейот ) это три (отдельные считаются отдельно).
Теперь рассмотрим задачу вычисления «самого легкого» сжатия данной строки с . После некоторых размышлений существует очевидный подход динамического программирования, который выполняется в или зависимости от точного подхода.
Однако мне сказали, что эта проблема может быть решена за , хотя я не могу найти источники о том, как это сделать. В частности, эта проблема была поставлена в недавнем конкурсе по программированию (проблема K здесь , последние две страницы). Во время анализа был представлен алгоритм , и в конце была упомянута псевдоквадратичная граница ( здесь, на отметке четыре минуты). К сожалению, докладчик упомянул только «сложную лемму о комбинаторике слов», поэтому теперь я пришел сюда, чтобы попросить решение :-)
источник
Ответы:
Если я вас не правильно понял, я думаю, что минимальная факторизация затрат может быть рассчитана за раз следующим образом.O(n2)
Для каждого индекса i мы вычислим группу значений для следующим образом. Пусть - наименьшее целое число, так что существует целое число удовлетворяющееДля этого конкретного , пусть будет наибольшим с этим свойством. Если такого существует, установите чтобы мы знали, что для этого индекса есть нулевые значения.(pℓi,rℓi) ℓ=1,2,… p1i≥1 r≥2 S[i−rp1i+1,i−p1i]=S[i−(r−1)p1i+1,i]. p1i r1i r pi Li=0 (pℓi,rℓi)
Пусть будет наименьшим целым числом, строго большим, чем удовлетворяющим также для некоторого . Как и прежде, возьмите как максимальное значение с фиксированным . В общем случае является наименьшим таким числом, строго большим, чем . Если такого существует, то .p2i (r1i−1)p1i S[i−r2ip2i+1,i−p2i]=S[i−(r2i−1)p2i+1,i] r2i≥2 r2i p2i pℓi (rℓ−1i−1)pℓ−1i pℓi Li=ℓ−1
Обратите внимание, что для каждого индекса i мы имеем из-за геометрического увеличения значений с . (если существует, он не просто строго больше, чем но больше, чем по крайней мере на Это устанавливает геометрическое увеличение. )Li=O(log(i+1)) pℓi ℓ pℓ+1i (rℓi−1)pℓi pℓi/2
Выше мы уже отмечали, что , ограничивая член суммой членом. Но на самом деле, если мы посмотрим на всю сумму, мы можем доказать что-то острее.∑jLj=O(∑jlog(j+1))=Θ(nlogn)
Рассмотрим дерево суффиксов обратной стороны (т. Дерево префиксов S). Мы будем взимать каждый вклад в сумму с ребра чтобы каждое ребро было начислено не более одного раза. Зарядите каждый к краю, исходящему из и идущему к . Здесь - лист дерева префиксов, соответствующий а nca обозначает ближайшего общего предка.T(S←) S ∑iLi T(S←) pji nca(v(i),v(i−pji)) v(i−pji) v(i) S[1..i]
Это показывает, что . Значения могут быть рассчитаны за время путем обхода дерева суффиксов, но я оставлю детали для последующего редактирования, если кому-то будет интересно.O(∑iLi)=O(n) (pji,rji) O(n+∑iLi)
Дайте мне знать, если это имеет смысл.
источник
Есть ваша начальная строка S длины n. Вот псевдокод метода.
Я намеренно дал немного подробностей о «конечных скобках», так как для стека и разборки нужно много шагов, что не позволило бы понять основной метод. Идея состоит в том, чтобы проверить возможное дальнейшее сокращение внутри первого. для примера ABCBCABCBC => (ABCBC) ² => (A (BC) ²) ².
Поэтому главное - сначала поискать большие периоды. Обратите внимание, что S [i] - это i-й член S, пропускающий любое "(", ")" или степень.
Это глобально O (n²log (n)).
источник