フェイス質問
https://www.luogu.org/problem/P3181
問題の解決策
#include <cstdioを> する#include <CStringの> する#include <iostreamの> する#include <ベクトル> の#define N 200050 の#define intを登録RI 使用して 名前空間STDを、 チャー S1 [N << 1 ]、S2 [N << 1 ]。 int型のL1、L2; INT CNT [N << 1 ]。 ベクター < INT >息子[N << 1 ]。 長い 長い ANS = 0 ; 構造体SAM { int型 FF [N << 1 ]、LEN [N << 1 ]。 INT CH [N << 1 ] [ 26 ]。 INTのパー[N << 1 ] [ 20 ]。 INTのトン[N << 1 ]。 int型ラス、TOTを。 ボイドのinit(){ ラス = TOT = 1 。 } ボイドが伸びる(int型C){ int型の NP = ++ TOT、P =ラス。ラス= NP。 LEN [NP] = LEN [P] + 1 。 CNT [NP] ++ ; 一方、(!P && CH [P] [C])CH [P] [C] = NP、Pの=のFF [P]。 もし(!p)はFF [NP] = 1; 他{ INT Q = CH [P]、[C]。 もし(LEN [Q] == lenの[P] + 1)FF [NP] = Q。 他の{ int型 NQ = ++ TOT; LEN [NQ] = LEN [P] + 1 。 用(RI i = 0 ; iは< 26 ; I ++)CH [NQ] [I] = CH [Q] [I]; FF [NQ] =のFF [Q]。 FF [NP] = FFの[Q] = NQ。 一方、(P && CH [P] [C] == Q)CH [P] [C] = NQ、P = FF [P]。 } } } ボイドmaketree(){ 用(RI I = 1; I <= TOT; iは++ )息子[FF [I]一back(I)。 } ボイド init_par(INT X){ パー[X] [ 0 ] =のFF [X]。 用(RI i = 1 ; iは= < 19 ; iは++)[X] [i]は= PAR PAR [PAR [X] [I- 1 ]] [I- 1 ]。 用(RI i = 0 ; I <息子[X] .size(); iは++ ){ init_par(息子[X] [I])。 CNT [X] + = CNT [息子[X] [I]]。 } } ボイド一致(チャー *のS){ int型のn = STRLEN(S + 1 )。 int型今= 1 ; int型 CC = 0 ; 用(RI i = 1 ; iが<= N; iが++ ){ 場合(CH [今] [S [I] - [ A ' ])は[今] [S [i]は- CHを= ' A ' ]、CC ++ ; 他の{ しばらく - (CH [今] [S [i]は!' A '今=の])FF [今]。 もし(!今){ 今 = 1 ; CC = 0 。 } 他{ CC = LEN [今] +1 ; 今 = CH [今] [S [I] - ' ' ]。 } } int型のx = 今。 ANS + =(CC-LEN [FF [X]] * 1LL)* 1LL * CNT [X]。 トン[FF [X]] ++ ; } } ボイド DP(INT X){ ため(RI i = 0 ; I <息子[X] .size(); iは++ ){ DP(息子[X] [I])。 トン[X] + = トン[息子[X] [I]]。 } ANS + = CNT [X] * 1LL *トン[X] * 1LL *(LEN [X] - LEN [FF [X]])。 } } SAM。int型 メイン(){ scanf関数(" %sの%sの"、S1 + 1、S2 + 1 )。 L1 = STRLEN(s1は+ 1 )。 sam.init(); 用(RI I = 1 sam.extend(S1 [i]が- ; I <= L1 I ++)は' A ' ); sam.maketree(); sam.init_par(1 )。 sam.match(S2)。 sam.dp(1 )。 printf(" %LLDする\ n " 、ANS)。 }