問題の意味:指定された文字列S、A、B。今あなたを聞かせてSは[A、B]の範囲内の各切断部は、プログラム番号を尋ねるように切り出します。
考える:そこ式、DP [I] =ΣDP [J](S [J + 1、i]は、 法的な範囲内で)。N | | M及びNは最長の共通のプレフィックス長LCP、文字列M> = N文字列の条件が= LCPであるとし、又は(LCP <| N | && M [LCP + 1]> N [LCA + 1 ]);共感未満。DPは、プレフィックスとO(N)で測定範囲を見つけることができます。
LCPは明らかに要件をexkmpすることができます。Z最近発見されたアルゴリズムが良く書かれています。ビットを試してみてください。ここでリンクアップしようとしている2回は、より快適になります。
#include <ビット/ STDC ++ H> の#define担当者(iは、、B)のための式(I ++ iは= int型;私は= Bを<) 使用して 名前空間STDを、 const int型 MAXN = 1000010 ; const int型のMod = 998244353 ; チャー S [MAXN << 1 ]、L [MAXN]、R [MAXN]。 INT [MAXN】Z1、Z2 [MAXN]、レナ、lenl、lenr。 ボイド Zは、(char型 []、char型 T []、INT Z []) { int型、F =のSTRLEN(A + 1)=のSTRLEN W(T + 1 )。 [F + 1 ] = ' &'; 担当者(I、1、W)[F + 1 + I] = tの[I]。INT、N = F + W + 1 。 Z [ 1 ] = N。INTは L = 0、R = 0 。 担当者(I、2 、N){ 場合(R <I)Z [I] = 0 ; 他の Z [i]は=分(R-I + 1、Z [I-L + 1 ])。 一方、(I + Z [i]が<= N [I + Z [i]は] && == [Z [i]が+ 1 ])Z [I] ++ ; もし(I + Z [1] - 1 > R)L = I、R = I + Z [1] - 1 。 } 担当者(I、1、W)Z [i]は= Z [F + 1 + I]; } INT DP [MAXN]和[MAXN]。 INT メイン() { scanf関数(" %S%S%S "、S + 1、L + 1、R + 1 )。 レナ = strlenを(S + 1)。lenl = STRLEN(L + 1)。lenrの=のSTRLEN(R + 1 )。 Z(L、S、Z1); Z(R、S、Z2)。 DP [レナ + 1 ] =和[レナ+ 1 ] = 1 。 以下のために(int型 =レナをIを、I> = 1 ; i-- ){ 和[I]=和[I + 1 ]。 もし(S [I] == ' 0 ')DP [I] =(L [ 1 ] == ' 0 ')* DP [I + 1 ]、和[I] =(SUM [I] + DP [I] )%のMod。 他{ int型 L = Iは、(i + lenr- lenl、R =分+ 2 、レナ)。 もし(Z1 [I] == lenl || S [I + Z1 [I]]> L [Z1 [I] + 1 ])L-- 。 もし(R <レナ&&(Z2 [I] == lenr || S [I + Z2 [I] <R [Z2 [I] + 1 ]))R ++ 。 もし(L <= R)DP [I] =(和[L + 1 ] -sum [R + 2] + MOD)%MOD、和[I] =(SUM [I] + DP [I])%のMod。 } } のprintf(" %d個の\ n "、DP [ 1 ])。 リターン 0 ;
}