このトピックでは、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 ; }