HDU補正第一の複数1006(hdu6583)タイプライターDP /サフィックスオートマトン

質問の意味:

タイプライターは、与えられた文字列、最低限必要なタイプされた文字列は、現在の新たな付加Pの文字列を過ごした後、現在の文字列の末尾に連続したサブ文字列の現在の文字列のコピーにQをとり、あり支出。

ソリューション:

DPと考えるのは簡単

ように私は、それぞれのために、私の前に最小コストプレイ文字を[i]はDPと呼ば

A = DP [I-1] + P 

jが最小であり、その結果のs B = DP [J] + Q [J + 1〜I]はSの連続するサブストリングの[1〜j]の値

実際には、カットバッククリックこの文字列は、フロント部分の背面がサブストリングの一部ではない参照し、そうでない場合、後方カット移動を配置する場合、元の文字列の前部には、文字列が概略背面部分です。

DP [I] =分(A、B)

私は=時間で、kは、このような最適なカット点jを発見した場合は、その後、議論するとき、I = K + 1、および最適なカットポイントまたは元J、jはこの背中を配置する必要がありますされますかノルウェー。

jはすでに元の文字列最短のカットポイントを作った、そして今あなたがパターン文字列の後ろに何かを追加する必要があるため、なぜ、元の文字列は長く、短くすることはできません。

データ構造があり、後方Jを移動する過程では、操作の最初のカットのパターン文字列があった場合、問題があることに注意してください、フロントサポートは、操作文字列のこのモードでは、それをカット?

サフィックスオートマトン。行サブストリング内の複数のノードを表すサフィックスオートマトン、最長の一つであり、残りは連続最長サブサフィックスであり、親ノードは、サフィックスの子ノードであり、その後、自動機に連続するためサブ、それをカットのトップを置くか、それが元のノードにとどまり、またはそれは親ノードに転送されます。

サフィックスオートマトンの複雑さOをインクリメントするように構成された(1)、O(1)の状態遷移の複雑

Oの合計時間複雑度(N)

書式#include <cstdioを> 
する#include <アルゴリズム> 
書式#include <CStringの>
 使用して 名前空間はstdを、
#define MAXN = 200005 #define種類= 26 構造体状態
{ 
    状態 *次の[種類]、* リンク。
    int型のlen; 
    状態()
    { 
        リンク = 0 
        LEN = 0 ; 
        memsetの(次に、0はsizeof (NEXT))。
    } 
}。
int型SZを。
状態ST [MAXN* 2 + 5 ]。
インライン状態 * newnode(INT LEN = 0 
{ 
    memsetの(ST [SZ] .Next、0はsizeof [SZ] .Next(ST))。
    ST [SZ] .link = 0 
    ST [SZ] .LEN = LEN。
    返す&ST [++ SZ ]。
} 
状態 *ルート、* 最後。
ボイド延びる(INT W)
{ 
    ステート *のP = 最後; 
    状態 * CUR = newnode(P-> LEN + 1 )。
    一方、(P && P->次に[W] ==0 
    { 
        P - >次に[W] = CUR。
        P = P - > リンク; 
    } 
    もし(P)
    { 
        状態 * Q = P-> 次に[W]。
        もし(P-> LEN + 1 == Q-> LEN)
            CUR >リンク= - ; Q
        
        { 
            状態 *クローン= newnode(P-> LEN + 1 )。
            memcpy(クローン - >次に、Q->次に、はsizeof(Q-> NEXT))。
            クローン - >リンク= Q-> リンク; 
            Q - >リンク=クローン; 
            CUR - >リンク= クローン;
            一方、(P && P->次に[W] == Q)
            { 
                P - >次に= [W] クローン。
                P = P - > リンク; 
            } 
        } 
    } 
     cur->リンク= ルート。
    最後 = CUR。
} 

の#defineっ長い長
 チャーS [MAXN]。
【MAXN] DP LL。
INT メイン()
{ 
    ながら(〜のscanf(" %sの"、S + 1 ))
    { 
        SZ= 0 ; 
        ルート = newnode()。
        最後 = ルート。
        LLのP、Q; 
        scanf関数(" %のLLDの%のLLD "、&​​P&Q)。
        INT、N = STRLEN(S + 1 )。
        int型 J = 1 ; 
        DP [ 1 ] = Pと、
        伸びる(S [ 1 ] - [ A ' ); 
        状態 * CUR = root->次に[S [ 1 ] - [ A ' ]。
        以下のためのint型私は=2 ; iが<= N; iが++ 
        { 
            DP [I] = DP [I- 1 ] + P。
            一方、1 
            { 
                ながら(!CUR =ルート&& cur->リンク- > LEN> = ij- 1)CUR = cur-> リンク。
                もし(cur->次に[S [I] - [ A ' ]!= NULL)
                { 
                    CUR = cur->次に[S [I] - ' ' ]。
                    破ります; 
                } 他の
                    (S [拡張 - ++ J] "
                A " ); 
            } 
            // coutの<< I <<」「<< J <<てendl; 
            DP [I] =分(DP [I]、DP [J] + Q)。
        } 
        のprintf(" %LLDする\ n " 、DP [N])。
    } 
}

 

PS:私は、サブセット、サブ、セクション、サブ文字列、列、間隔の違いを理解したことがありません、一般的に「非連続したサブ文字列/配列」、「連続ストリング/シーケンス」を呼び出すために使用されます

おすすめ

転載: www.cnblogs.com/isakovsky/p/11246450.html