Факторизація слів за


12

Враховуючи два рядки , ми пишемо для їх конкатенації. Давши рядок і ціле число , запишемо для конкатенаціїS1,S2S1S2Sk≥1(S)k=SS⋯Sk копійS . Тепер, задавши рядок, ми можемо використовувати це позначення для його «стиснення», тобтоAABAAB може бути записано як((A)2B)2 . Назвемо вагукомпресіїчисло символів, що з’являються в ній, тому вага((A)2B2) складаєтьсядвох, а вага(AB)2A (встисненнізABABA ) три (окреміA з підраховуються окремо).

Тепер розглянемо проблему обчислення "найлегшого" стиснення заданого рядка S з |S|=n . Після роздумів існує очевидний динамічний підхід програмування, який працює в O(n3log⁡n) або O(n3) залежно від точного підходу.

Однак мені сказали, що цю проблему можна вирішити за O(n2log⁡n) час, хоча я не можу знайти джерел, як це зробити. Зокрема, ця проблема була задана в недавньому конкурсі програмування (проблема K тут , останні дві сторінки). Під час аналізу був представлений алгоритм O(n3log⁡n) , а в кінці згадували псевдо квадратичну межу ( тут на позначці чотирьох хвилин). На жаль, ведучий згадував лише «складну лемму про комбінаторику слова», тому зараз я прийшов сюди, щоб попросити рішення :-)


Просто випадкова властивість: Якщо для рядка маємо S = X a = Y b , то також повинно бути, що S = Z | S | / gcd ( | X | , | Y | ) [я тут виправив помилку], причому Z має довжину gcd ( | X | , | Y | ) (яка не може бути довшою ні X, ні YSS=Xa=YbS=Z|S|/gcd(|X|,|Y|)Zgcd(|X|,|Y|)XY). Не впевнений, наскільки це корисно. Якщо ви вже виявили, що і знаєте, що S містить щонайменше 2 різних символи, і тепер шукаєте коротший Y такий, що S = Y b , то вам потрібно лише спробувати префікси Y з X довжиною, яка ділиться | X | . S=XaSYS=YbYX|X|
— j_random_hacker

Проблема полягає в тому, що навіть після зменшення всіх можливих , вам все одно потрібно зібрати відповідь кубічним DP по підсегментам (тобто D P [ l , r ] = min k D P [ l , k ] + D P [ k + 1 , r ] ), тож після цього ще потрібно виконати додаткову роботу ...XaDP[l,r]=minkDP[l,k]+DP[k+1,r]
— Timon Knigge

Я бачу, що ти маєш на увазі. Я думаю, вам потрібне якесь відношення домінування, яке позбавляє деяких значень не потребувати тестування - але я не міг придумати його. Зокрема, я розглядав наступне: Припустимо, S [ 1 .. i ] має оптимальну факторизацію S [ 1 .. i ] = X Y k при k > 1 ; чи можливо, що існує оптимальне рішення, в якому S розбивається на X Y j Z з j < k ? На жаль, відповідь - такkS[1..i]S[1..i]=XYkk>1SXYjZj<k , S [ 1..4 ] має оптимальну факторизацію ( A B ) 2 , але єдиною оптимальною факторизацією для S є A B ( A B C ) 2 . S=ABABCABCS[1..4](AB)2SAB(ABC)2
— j_random_hacker

Відповіді:


1

Якщо я вас не розумію, я думаю, що мінімальна вартість витрат може бути обчислена за O(n2) час таким чином.

Для кожного індексу i обчислимо купу значень (piℓ,riℓ) для ℓ=1,2,… наступним чином. Нехай pi1≥1 - найменше ціле число, таке, що існує ціле число r≥2 задовольняє

S[i−rpi1+1,i−pi1]=S[i−(r−1)pi1+1,i].
Для цього конкретногоpi1 , нехайri1 є найбільшимr з цією властивістю. Якщо такогоpi немає, встановітьLi=0 щоб ми знали, щодля цього індексує нульові(piℓ,riℓ) значення.

Нехай pi2 - найменше ціле число, строго більше, ніж (ri1−1)pi1 задовольняє також

S[i−ri2pi2+1,i−pi2]=S[i−(ri2−1)pi2+1,i]
для деяких ri2≥2 . Як і раніше, приймайте ri2 як максимальний з фіксованим pi2 . Загалом piℓ - найменша така кількість, строго більша, ніж (riℓ−1−1)piℓ−1 . Якщо такого piℓ існує, то Li=ℓ−1 .

Зауважимо, що для кожного індексу i маємо Li=O(log⁡(i+1)) за рахунок значень piℓ геометрично збільшуються з ℓ . (якщо piℓ+1 існує, це не просто суворо більше, ніж (riℓ−1)piℓ але більше, ніж принаймні piℓ/2 Це встановлює геометричне збільшення.)

Припустимо, тепер всі (piℓ,riℓ) значення задані нам. Мінімальна вартість задається повторенням

dp(i,j)=min{dp(i,j−1)+1,minℓ(dp(i,j−rjℓpjℓ)+dp(j−rjℓpjℓ+1,j−pjℓ))}
з розумінням того, що дляi>jвстановимоdp(i,j)=+∞. Таблицю можна заповнити заO(n2+n∑jLj).

Ми вже відзначали вище , що ∑jLj=O(∑jlog⁡(j+1))=Θ(nlog⁡n) з допомогою обмежує термін суми на термін. Але насправді, якщо ми подивимось на всю суму, ми можемо довести щось гостріше.

Розглянемо дерево суфікса T(S←) звороту S (тобто дерево префікса S). Ми стягуватимемо кожен внесок на суму ∑iLi до краю T(S←) так що кожне ребро буде нараховано не більше одного разу. Заряджайте кожну pij до краю, що виходить від nca(v(i),v(i−pij)) і рухаючись у напрямку v(i−pij) . Тутv(i) - лист дерева префікса, що відповідаєS[1..i] а nca позначає найближчого спільного предка.

Це показує, що O(∑iLi)=O(n) . Значення (pij,rij) можна обчислити за часом O(n+∑iLi) шляхом проходження дерева суфіксів, але я залишу деталі для подальшого редагування, якщо когось цікавить.

Дайте мені знати, чи це має сенс.


-1

Існує ваш початковий рядок S довжиною n. Ось псевдокод методу.

next_end_bracket = n
for i in [0:n]: # main loop

    break if i >= length(S) # due to compression
    w = (next_end_bracket - i)# width to analyse

    for j in [w/2:0:-1]: # period loop, look for largest period first
        for r in [1:n]: # number of repetition loop
            if i+j*(r+1) > w:
                break r loop

            for k in [0:j-i]:
                # compare term to term and break at first difference
                if S[i+k] != S[i+r*j+k]:
                    break r loop

        if r > 1:
            # compress
            replace S[i:i+j*(r+1)] with ( S[i:i+j] )^r
            # don't forget to record end bracket...
            # and reduce w for the i-run, carrying on the j-loop for eventual smaller periods. 
            w = j-i

Я навмисно дав невеликі подробиці про "кінцеві дужки", оскільки для цього потрібно багато кроків для складання та атаки, що дозволило б чітко визначити основний метод. Ідея полягає у випробуванні можливого подальшого скорочення всередині першого. для прикладу ABCBCABCBC => (ABCBC) ² => (A (BC) ²) ².

Тому головне - спочатку шукати великі періоди. Зауважте, що S [i] - i-й член S, який пропускає будь-які "(", ")" або потужність.

  • i-петля - O (n)
  • j-петля - O (n)
  • r + k-петлі - це O (log (n)), оскільки він зупиняється на першій різниці

Це глобально O (n²log (n)).


Мені не зрозуміло, що петлі r і k є O (log n) - навіть окремо. Що гарантує виявлення різниці після максимум O (log n) ітерацій?
— j_random_hacker

Я правильно розумію, що ви жадібно стискаєте? Оскільки це невірно, розглянемо, наприклад, ABABCCCABCCC, який слід розподілити як AB (ABC ^ 3) ^ 2.
— Тімон Найге

Так, ви з цим абсолютно праві, я думаю про це.
— Оптідад
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.