Gタイトル:サブシーケンス
問題の意味:2文字の文字列番号が与えられ、S、Tは、Tのサブシーケンスよりも大きな正の整数の後にサブシーケンスsの数として計算されます。
分析:サブシーケンス長T Sが得られる前処理の数を組み合わせることにより、ラージT(0負先頭)の一定の比率よりも大きい、SがTよりも大きいtに等しいキーオペレーター配列の長さは、いくつか存在します。:はっきり[I]は[j]は状態を示している位置マークDP、DPの状態で右から左にS、Tと、本明細書DP練習を使用Tのi及びS jのフロント列の前の文字列の最大数を。状態ごとに、それがオン状態の位置が含まれている必要があり、その後、新しい最初のエントリによると、数よりも多くの最初のアイテムと同じプラスtとより大きい場合に使用するように、選択された原理が上で選択されプラス選択されたヘッドの組み合わせの数は、同じ場合も追加することができます値DPは上に記録され、これまでに選択します。
書式#include <cstdioを> 使用して 名前空間はstdを、 typedefの長い 長いLL。 const int型 MAXN = 3007 ; const int型のmod = 998244353 ; LL C [MAXN] [MAXN]。 LL DP [MAXN] [MAXN]。 チャーS [MAXN]、T [MAXN]。 無効INIT_C(){ C [ 0 ] [ 0 ] = 1 。 以下のために(int型 I = 1 ; I <MAXN; I ++ ){ C [i]が[ 0 ] = 1 ; 以下のための(int型J = 1 ; J <= MAXN。J ++ ){ C [I] [J] =(C [I- 1 ] [J] + C [I- 1 ] [J- 1 ])%MOD。 } } } int型のmain(){ INIT_C()。 int型T; scanf関数(" %のD "、&T)。 INTのN、M。 一方、(T-- ){ scanf関数(" %d個の%のD "、&N、&M)。 scanf関数(" %sの%sの" 、S、T)。 以下のための(int型私は=0 ; I <= N。私は++ ){ ための(int型 J = 0 ; J <= Mであり、j ++ ){ DP [I] [J] = 0 ; } } LL ANS = 0 。 // 线性递推的二维DP のための(INT I = M- 1 ; I> = 0 ; i-- ){ ため(INT J = N- 1、J> = 0 ; j-- ){ (DP [ J] [I] + = DP [J + 1 ] [I])%= MOD。 //終わりにセキュリティ IF(S [J] == T [I])(DP [J] [I] + = DP [J + 1。 ] [私は+ 1。 ])%= MOD; // ための機会を追加することができ 、他の IF( S [J]> T [I])(DP [J] [I] + = C [N- 1。 -j] [M- 1)-1]; // 選択された思考、それが選択された一つのC DP再帰的な計算ではなく、直接、残酷な成長を意味する } } ANS + DP = [ 0 ] [ 0 ]; // のprintf( "%LLD ANS = \ N-"、ANS) のための(INT I = N- 1、Iは> = 0 ; i-- ){ IF =(S [I]!' 0 '){ について(INT J =ニッケル; J> = Mの+ 1、J、){ // のprintf( "%D%D \ N-"、I、J); (ANS + C = [N- 1 -i] [ J- 1 ])MOD =%; // 選択された原理上掲 } } } のprintf(" %LLDの\のN- " 、ANS); } }