회문 트리 dfs-- 가축 오프 더 학교 여섯 번째 C

/ * 
SET는 우리가 처음 상동 나무를 구축, 상동 서열의 성격과 달라야합니다 
포인터가 NXT b로 도달 할 수있을 때, 또는 b가 실패 포인터를 통해 도달 할 수있는, B는 문자열입니다 
나무 상동에 대한 u는 우리가 두 개의 부분으로의 접합에 관련 될 수있는 각 노드 : 
    서브 트리 아래 1 접속점, 점선 측의 U의 부분에 의해 얻어 질 수있는 모든 노드 설정 사이즈 크기 [U ] 
    상향 체인 실패 2 노드는이 체인에있는 모든 노드 회문 접미사 U되어 설정 크기 TOT [U]는 
문자열 다음 체인상의 모든 점은, 하위 트리 U이다 페일 크기 때문에 U 기여 [U]는 * TOT [U ] 
다음 무거운 가야 : 유, 체인 V는 U와 일치되지 않을 수 V의 자손, U 형 기부의 일부가 부서 계산한다 일치하고 명확 V 그 운영자가 필요하지 않습니다 
그래서에 재귀 되돌아의 출시 전에 마주 마크 지점을 방문하는 실패 DFS 사용 
 * / 
사용법 #include <비트 / STDC ++ H.>
 은 Using  네임 스페이스 STD는,
 #DEFINE MAXN 100005는
 구조체 팸 {
     INT NXT를 [MAXN] [ 26는 LEN [MAXN], 페일 [MAXN]
     int로 , NUM [MAXN, CNT는 [MAXN]
     지능S [maxn, N, P, 마지막;
    INT newnode ( INT l) { 
        memset 함수 (NXT [P] 0 , sizeof 연산자 NXT [P]); 
        LEN [P]는 = L 단계; 
        NUM [P] = CNT [P] = 0 ;
        반환 페이지를 ++ ; 
    } 
    공극 초기화 () { 
        P = 0 ; 
        newnode ( 0 ); 
        newnode ( - 1 ); 
        [실패 0 ] = 1 ; 
        마지막 = N = 0 ; 
        S [ 0= - 1 ; 
    } 
    INT get_fail ( INT X) {
         동안 (S [N-LEN [X] - 1 ] = S [N]!) X = 실패 [X];
        반환 X를; 
    } 
    공극 추가 ( INT의 c) { 
        C - = ' ' , S [N ++] =의 C;
        INT CUR = get_fail (마지막);
        경우 (! NXT [CUR는 [C]) {
             int로 (LEN [CUR] + = 지금 newnode를 2 ); 
            실패 [현재] = NXT [get_fail (실패 [CUR])] [C] 
            NXT [CUR] [C]= 이제; 
            NUM [현재] = NUM [실패 [현재] + 1 ; 
        } 
        지난 = NXT [CUR] [C] 
        CNT [마지막] ++ ; 
    } 
    int로 [maxn] 어린 아이 [maxn] 힘 [maxn, 크기;
    보이드 dfs1 ( INT U) { 
        크기 [U] = 1 ;
        위한 ( int로 I = 0 ; I는 < 26 ; ++ 나 )
             의 경우 (NXT [U] [I]) {
                 INT의 V = NXT [U] [I]; 
                dfs1 (V); 
                크기 [U] + =크기 [V]; 
            } 
    } 
    공극 DFS2 ( INT U) { 
        TOT [U] = 0 ;
         ( INT X = U;! 힘 [X] && x> 1 ; X = 실패 [X]) 
            TOT [U] ++, 힘 [X] = U;
        위한 ( int로 I = 0 ; I는 < 26 ; ++ 나 )
             의 경우 (NXT [U] [I]) {
                 INT의 V = NXT [U] [I]; 
                DFS2 (V); 
            } 
         ( INT X = U; 힘 [X] == U && x> 1 ; X =[X]) 실패     
            힘이 [X] = 0 ; 
    } 
     계수 () {
         위해 ( int로 난 = P- 1 ; i가> = 2 ; 난 - ) 
            CNT [실패 [I] + = CNT [I]; 
        dfs1 ( 0 ) DFS2 ( 0 ); 
        dfs1 ( 1 ) DFS2 ( 1 );
          입술 = 0 ;
        위한 ( int로 I = 2 ; P <i가 나는 ++ ) 
            입술 = 입술 크기 + [I] *을어린 아이 [I]을;
        반환 RES- (P- 2 );    
    } 
} TR; 
문자 S [maxn]; 

INT 의 main () {
     INT의 t; CIN >> t;
     ( INT의 TT = 1 ; TT <= t; TT ++ ) { 
        는 scanf ( " %의 S ' , S);
        INT LEN = strlen 함수 (S); 
        tr.init (); 
        위한 ( int로 I = 0 ; I <렌; 내가 ++ ) 
            tr.add (S [I]); 
        의 printf ( " 케이스 # 1 %의 D % LLD \ 없음 " , TT, tr.count ());
    } 
}

 

추천

출처www.cnblogs.com/zsben991126/p/11329261.html