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


12

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

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

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


Просто випадкова властивість: Якщо для рядка маємо 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, наступним чином. Нехай pi11 - найменше ціле число, таке, що існує ціле число r2 задовольняє

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

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

S[iri2pi2+1,ipi2]=S[i(ri21)pi2+1,i]
для деяких ri22 . Як і раніше, приймайте ri2 як максимальний з фіксованим pi2 . Загалом pi - найменша така кількість, строго більша, ніж (ri11)pi1 . Якщо такого pi існує, то Li=1 .

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

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

dp(i,j)=min{dp(i,j1)+1,min(dp(i,jrjpj)+dp(jrjpj+1,jpj))}
з розумінням того, що дляi>jвстановимоdp(i,j)=+. Таблицю можна заповнити заO(n2+njLj).

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

Розглянемо дерево суфікса T(S) звороту S (тобто дерево префікса S). Ми стягуватимемо кожен внесок на суму iLi до краю T(S) так що кожне ребро буде нараховано не більше одного разу. Заряджайте кожну pij до краю, що виходить від nca(v(i),v(ipij)) і рухаючись у напрямку v(ipij) . Тут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.