/ * 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 ()); } }