zamanında sözcük çarpanlarına ayırma


12

Verilen iki dizeleri şunu yazabiliriz onların Ulama için. Bir dize Verilen ve tamsayı şunu yazabiliriz ait Ulama için kopyaları . Şimdi bir dize verildiğinde, bu gösterimi 'sıkıştırmak' için kullanabiliriz, yani olarak yazılabilir . Diyelim bir ağırlığını diyoruz sıkıştırma ağırlığı yüzden, içinde görünen karakter sayısı ikidir ve ağırlığı (a sıkıştırma ait ) üçtür (ayrıS 1 , S 2 S1,S2S 1 S 2S1S2 S Sk 1 k1( S ) k = S S S (S)k=SSSk kS SA A B A A B AABAAB( ( A ) 2 B ) 2((A)2B)2( ( A ) 2 B 2 ) ((A)2B2)( A B ) 2 A(AB)2AA B A B A ABABAAA ler) ayrı ayrı sayım yapılır.

Şimdi belirli bir dizesinin 'en hafif' sıkıştırmasını ile hesaplama problemini düşünün . Biraz düşündükten sonra , tam yaklaşıma bağlı olarak veya çalışan bariz bir dinamik programlama yaklaşımı vardır .S S| S | = N |S|=nO ( n, 3 günlük , n ) O(n3logn)O ( n, 3 )O(n3)

Ancak, bu sorunun zamanında çözülebileceği söylendi , ancak bunun nasıl yapılacağı ile ilgili herhangi bir kaynak bulamıyorum. Özellikle, bu sorun yakın tarihli bir programlama yarışmasında verildi ( burada K sorunu , son iki sayfa). Analiz sırasında bir algoritması sunuldu ve sonunda yalancı kuadratik bağdan bahsedildi ( burada dört dakika işaretinde). Ne yazık ki, sunucu sadece 'karmaşık bir kelime birleştirici lemmaya' atıfta bulundu, bu yüzden şimdi buraya çözüm istemeye geldim :-)O ( n 2 günlük n )O(n2logn)O ( n 3 günlük n )O(n3logn)


Sadece rastgele bir özellik: dizesi için , o zaman [ Ben burada bir hata düzeltildi], uzunluğu (ya ya da daha uzun olamaz ) sahip. Bunun ne kadar yararlı olduğundan emin değilim. Zaten bulduysanız o ve biliyoruz en az 2 farklı karakterler içeriyor ve şimdi daha kısa arıyoruz öyle ki , o zaman sadece önekleri denemek gerekir arasında uzunluğuna sahip bölen.S SS = X a = Y bS=Xa=Yb S = Z | S | / gcd ( | X | , | Y | )S=Z|S|/gcd(|X|,|Y|) Z Zgcd ( | X | , | Y | ) gcd(|X|,|Y|)X XY YS = X aS=Xa S SY YS = Y bS=Yb Y YX X| X ||X|
j_random_hacker

Sorun şu ki, olası tüm sonra bile , cevapları kübik DP tarafından alt bölümler üzerinde toplamanız gerekir (yani ), bu yüzden bundan sonra yapılması gereken bazı ekstra işler var ...X a D P [ l , r ] = dk k D P [ l , k ] + D P [ k + 1 , r ]XaDP[l,r]=minkDP[l,k]+DP[k+1,r]
Timon Knigge

Ne demek istediğini anlıyorum. Bazı değerlerinin test edilmesi gerekliliğini ortadan kaldıran bir tür hakimiyet ilişkisine ihtiyacınız olduğunu düşünüyorum - ama bir tane düşünemedim. Özellikle, aşağıdaki olarak: Varsayalım optimal factorisation sahip ile ; ile olarak çarpanlaştırıldığı optimal bir çözüm olması mümkün müdür ? İçin: Maalesef Cevap evet , optimum factorisation sahiptir , ancak için tek en factorisation olan .kkS[1..i]S[1..i]S[1..i]=XYkS[1..i]=XYkk>1k>1SSXYjZXYjZj<kj<kS=ABABCABCS=ABABCABCS[1..4]S[1..4](AB)2(AB)2SSAB(ABC)2AB(ABC)2
j_random_hacker

Yanıtlar:


1

Eğer sizi yanlış anlamıyorsam, minimum maliyet çarpanlarının zamanında aşağıdaki gibi hesaplanabileceğini düşünüyorum.O(n2)O(n2)

Her indeks i için, için bir grup değeri aşağıdaki gibi hesaplayacağız. Let bir tamsayı olduğu gibi tam sayı küçük olması tatminBu özel , bu özelliğe sahip en büyük . Böyle bir yoksa, bu için sıfır değerleri olduğunu bildiğimiz için ayarlayın .( p i , r i ) (pi,ri)= 1 , 2 , =1,2,p 1 i1 p1i1r 2 r2S [ i - r p 1 i + 1 , i - p 1 i ] = S [ i - ( r - 1 ) p 1 i + 1 , i ] .

S[irp1i+1,ip1i]=S[i(r1)p1i+1,i].
p1ip1ir1ir1irrpipiLi=0Li=0(pi,ri)(pi,ri)

Let kesin daha büyük en küçük tam sayı olduğu karşılayan, aynı şekilde, bazı . Daha önce olduğu gibi, sabit sahip maksimum olacak şekilde alın . Genel olarak , den kesinlikle daha büyük olan en küçük sayıdır . Böyle bir yoksa, .p2ip2i(r1i1)p1i(r1i1)p1iS[ir2ip2i+1,ip2i]=S[i(r2i1)p2i+1,i]

S[ir2ip2i+1,ip2i]=S[i(r2i1)p2i+1,i]
r2i2r2i2r2ir2ip2ip2ipipi(r1i1)p1i(r1i1)p1ipipiLi=1Li=1

Her dizin i için, değerleri ile geometrik olarak arttığından olduğuna . ( varsa, sadece kesinlikle daha büyük değil, en azından daha büyüktür . Bu geometrik artışı oluşturur. )Li=O(log(i+1))Li=O(log(i+1))pipip+1ip+1i(ri1)pi(ri1)pipi/2pi/2

Şimdi tüm değerlerin bize verildiğini varsayalım . Minimum maliyet için ayarladığımız anlayışıyla . Tablo sürede .(pi,ri)(pi,ri)dp(i,j)=min{dp(i,j1)+1,min(dp(i,jrjpj)+dp(jrjpj+1,jpj))}

dp(i,j)=min{dp(i,j1)+1,min(dp(i,jrjpj)+dp(jrjpj+1,jpj))}
i>ji>jdp(i,j)=+dp(i,j)=+O(n2+njLj)O(n2+njLj)

Yukarıda , toplam terimi terime göre sınırlayarak daha önce gözlemledik . Ama aslında, toplamın tamamına bakarsak, daha keskin bir şey kanıtlayabiliriz.jLj=O(jlog(j+1))=Θ(nlogn)jLj=O(jlog(j+1))=Θ(nlogn)

Soneki ağacı düşünün ait ters (yani, S önek ağacı). Bu toplamı her katkı şarj olur bir kenarına her bir kenarı bir kez en şarj edilecektir. Her den yayılan ve yönünde doğru . Burada , karşılık gelen önek ağacının ve nca, en yakın ortak atası belirtir.T(S)T(S)SSiLiiLiT(S)T(S)pjipjinca(v(i),v(ipji))nca(v(i),v(ipji))v(ipji)v(ipji)v(i)v(i)S[1..i]S[1..i]

Bu . Değerler , zamanında sonek ağacının geçişi ile hesaplanabilir, ancak ilgilenen varsa ayrıntıları sonraki bir düzenlemeye bırakacağım.O(iLi)=O(n)O(iLi)=O(n)(pji,rji)(pji,rji)O(n+iLi)O(n+iLi)

Bunun mantıklı olup olmadığını bana bildirin.


-1

N uzunluğunda ilk S dizeniz var. İşte yöntemin sözde kodu.

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

Çekirdek yönteminin net olmamasına izin verecek ve istiflemek için çok fazla adım gerektirdiğinden kasıtlı olarak "uç braketleri" hakkında çok az ayrıntı verdim. Fikir, ilkinde bir sonraki daralmayı test etmektir. örnek için ABCBCABCBC => (ABCBC) ² => (A (BC) ²) ².

Yani asıl nokta önce büyük dönemler aramaktır. S [i] 'nin S'nin herhangi bir "(", ")" veya gücü atlaması için kullanılan terim olduğunu unutmayın.

  • i-döngüsü O (n) 'dir
  • j-döngüsü O (n) 'dir
  • r + k-döngüler ilk farkta durduğundan O (log (n))

Bu küresel olarak O (n²log (n)).


Bana göre, r ve k döngülerinin O (log n) olduğu ayrı ayrı bile. En fazla O (log n) yinelemesinden sonra bir farkın bulunmasını sağlayan nedir?
j_random_hacker

Açgözlülükle sıkıştırdığınızı doğru anladım mı? Bu yanlış olduğundan, örneğin AB (ABC ^ 3) ^ 2 olarak çarpanlarına ayırmanız gereken ABABCCCABCCC'yi düşünün.
Timon Knigge

Evet, bu konuda tamamen haklısın, bunu düşünmeliyim.
Optidad
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.