[HAOI2016は、同じ文字を見つけます]

フェイス質問

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)。
}

 

おすすめ

転載: www.cnblogs.com/shxnb666/p/11279202.html