時間での単語分解


12

2つの文字列与えられた場合、それらの連結のためにを記述します。文字列を考えるとと整数、我々は書くの連結のためののコピー。文字列が与えられると、この表記を使用して「圧縮」できます。つまり、はとして記述できます。レッツ・コールの体重圧縮そこに登場するキャラクタの数、重量のように、 2である、との重量(圧縮の)3であります(分けるS1,S2S1S2Sk1(S)k=SSSkSAABAAB((A)2B)2((A)2B2)(AB)2AABABAA単数または複数)は別々にカウントされます。

今、与えられた文字列の「最軽量」圧縮計算する問題を検討と。少し考えた後、正確なアプローチに応じてまたはで実行される明らかな動的プログラミングアプローチがあり。S|S|=nO(n3logn)O(n3)

ただし、この問題は時間で解決できると言われていますが、これを行う方法に関する情報源は見つかりません。具体的には、この問題は最近のプログラミングコンテスト(問題K ここ、最後の2ページ)で与えられました。分析中にアルゴリズムが提示され、最後に疑似2次境界が示されました(ここでは4分マーク)。悲しいことに、プレゼンターは「複雑な単語の組み合わせ補題」に言及しただけだったので、解決策を求めるためにここに来ました:-)O(n2logn)O(n3logn)


S = X a = Y b S = Z | S | / gcd | X || Y | Z gcd | X || Y |XSS=Xa=YbS=Z|S|/gcd(|X|,|Y|)Zgcd(|X|,|Y|)XS = X a S Y S = Y b Y X | X |YS=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 kk > 1であると仮定します。Sj < kX Y j Zとして因数分解される最適な解が存在する可能性はありますか?残念ながら、答えはイエスです。kS[1..i]S[1..i]=XYkk>1SXYjZj<k S [ 1..4は最適な因数分解有するA B 2を、しかしためのユニークな最適の因数 Sはある A 、B A B C 2S=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)ことを既に観察しました。しかし、実際に全体を見ると、よりシャープなものを証明できます。

Sの逆のサフィックスツリーT(S)(つまり、Sのプレフィクスツリーを考えます。合計iLiへの各寄与をT(S)エッジにチャージしS、各エッジが最大1回チャージされるようにします。各pijnca(v(i),v(ipij))から発してvに向かうエッジにチャージしますv(ipij)。ここで、v(i)S[1..i]対応するプレフィックスツリーの葉で、ncaは最も近い共通の祖先を示します。

これは、O(iLi)=O(n)ます。値(pij,rij)は、サフィックスツリーのトラバーサルによって時間O(n+iLi)で計算できますが、興味がある場合は詳細を後の編集に任せます。

これが理にかなっているかどうか教えてください。


-1

長さnの初期文字列Sがあります。メソッドの擬似コードは次のとおりです。

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]は、「(」、「)」または累乗をスキップするSのi番目の項であることに注意してください。

  • iループはO(n)
  • jループはO(n)
  • r + k-loopsはO(log(n))で、最初の差で停止します

これはグローバルにO(n²log(n))です。


rループとkループがO(log n)であることは明確ではありませんが、別々であってもです。せいぜいO(log n)回の反復後に違いが見つかることを保証するものは何ですか?
j_random_hacker

あなたが貪欲に圧縮していることを正しく理解していますか?それは間違っているので、たとえばAB(ABC ^ 3)^ 2として因数分解すべきABABCCCABCCCを考慮してください。
ティモンKnigge

ええ、あなたはそれについて完全に正しいです、私はこれについて考えなければなりません。
Optidad
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.