H.サブ配列(ハードバージョン)DP

H.サブ配列(ハードバージョン)

このトピックでは、DPは、に取得しようとの意志を理解するために、問題への解決策を読む方法がわからない、ああ、非常に困難です。

最初のDP [I] [j]は、jの長さが異なる部分文字列の数に、フロントi番目の文字を表します。

DP [I] [j]はDP [I-1] [J-1] + DPを= [I]、[J-1]これは、文字を選択または選択されていないことを意味します。

ただし、文字の繰り返しが発生しており、このシフトは少し問題となる場合、それはより多くのいくつかのケースを支払うことになり、これは文字を繰り返すことになることに注意してください。

例えばxyzabca DP [7] [2]長さの最初の7文字2から選択される文字の数であり、DP [7] [2] = DP [6] [1] + DP [6] [2]

DPは、[6] [1]から転送され、最初の7つの文字を選択しなければならないことを意味するので、XA YX ZAこの答えがあるでしょう、

この答えDP [4] [2] = DP [3] [1] + DP [3] [2]この転送、DP [3] [1]ので、この答えが含まれている場合DPを削除[3] [1]

文字は、一般的なフロントxが発生した場合には、その後、サブシーケンスを終了するxを省略した文字の長さに行くマイナス1。

= DP【中古[I] -1] [J-1] - DP [I] [J]即

これらはあなたがコードを知ってノックすることができます。 

書式#include <cstdioを> 
する#include <CStringの> 
の#include <アルゴリズム> 
書式#include <キュー> 
の#include <マップ> 
書式#include <ベクトル> 
の#include <cstdlib> 
書式#include <iostreamの>
 に#define INF 0x3f3f3f3f
 の#define inf64 0x3f3f3f3f3f3f3f3f
 使用して 名前空間STD; 
typedefの長い 長いLL。
const  int型 MAXN = 2E5 + 10 
LLのDP [ 110 ] [ 110 ]。
int型のプレ[ 110 ]。
チャーS [MAXN]。

INT {main()の
    LL N、K。
    scanf関数(" %のLLDの%のLLD "、&​​N&K)。
    scanf関数(" %sの"、S + 1 )。
    DP [ 0 ] [ 0 ] = 1 以下のためにint型 i = 1 ; iが<= N; iは++ ){ 
        DP [I] [ 0 ] = 1 ;
        INT J = 1 ; J <= I; J ++ ){ 
            DP [I] [J] = DP [I- 1 ] [J- 1 ] + DP [I- 1] [J]。
            もし(予備[S [I] - [ A ' ])DP [I]、[J] - = DP [プレ[S [I] - ' ' ] - 1 ] [J- 1 ]。
            DP [I] [J] = 分(DP [I]、[J]、K)。
        } 
        事前[S [I] - [ A ' ] = I。
    } 
    LL和 = 0、ANS = 0 ブールフラグ= 0 以下のためにint型 I = N; I> = 0 ; i-- ){
         場合(和+ DP [n]は[I]> = K){
            フラグ = 1 
            ANS + =(NI)* 1LL *(K- 合計)。
            破ります; 
        }  + = DP [n]は[I]。
        ANS + =(NI)* DP [n]は[I]。
    } 
    であれば(フラグ)のprintf(" %LLDする\ n " 、ANS)。
    のprintf(" -1 \ nを" );
    リターン 0 ; 
}
コードの表示

 

おすすめ

転載: www.cnblogs.com/EchoZQN/p/11620762.html