회문 트리 템플릿 제목

주제 링크  https://www.luogu.org/problem/P3649

제목 설명

당신에게 라틴 소문자의 캐릭터 부여  S S.을 우리는 정의  문자열의 현재 가치의의 하위 문자열  문자열의 길이를 곱한 발생 s의 수.

당신이 문자열을  S S를, 상동 문자열의 모든 존재의 최대 값을 찾을 수 있습니다.

#INCLUDE <비트 / STDC ++ H.>
 #DEFINE 메트로 (A, B)가 memset (A, B, sizeof의 (A))
 #DEFINE LL 긴 롱
 #DEFINE ULL 부호 긴 롱
 은 USING  공간 STD; 

CONST의  INT MAXN = 300,005 ;
 CONST  INT N = 26이다 ;
 구조체 팸을 {
     INT NE [MAXN [N]; // 현재 문자열 포인팅 구성하는 문자열의 양단에 동일 다음 포인터 다음 트라이 포인터 등 플러스 
    INT 페일 [MAXN] / / 페일 불일치 노드 포인터로 이동 포인터 실패 
    INT CNT [MAXN]; //는 본질적 I 투고 문자열로 나타내는 다른 노드들이 완료되지 않은 경우 (얻어진 수를 나타내고, 최종 횟수 () 함수 실행 후 다시 올바른)는 
    INT , NUM [MAXN] //팔린 드롬 서열의 팔린 드롬 서열의 단부로 나타내는 긴 팔린 드롬 서열의 우측 노드 점 난의 수를 나타낸다 
    INT LEN [MAXN]; // LEN [I] 노드 I로 표시되는 팔린 드롬 서열의 길이를 나타낸다 (a 노드는 팔린 드롬 서열)을 나타낸다 
    지능 , S는 [MAXN] // 추가 문자 저장 
    지능 마지막; // 노드 형성된 새로 추가하는 문자로 표시 긴 팔린 드롬 서열 포인트. 
    INT N-; //은 추가 할 문자의 수를 나타냅니다. 
    INT P; // 추가 된 노드의 수를 나타냅니다. 
    INT newNode ( INT의 L) { // 새로운 노드를 생성 
        을위한 ( int로 된 I = 0 ; I는 N을 <; I는 ++) NE [P] [I] = 0 ; 
        CNT가 [P]를 NUM [P] = 0 ; 
        LEN [P]를 = L;
        반환 P ++를 ; 
    } 
    무효화 (초기화)을 { // 초기화 
        P = 0 ; 
        newNode ( 0 ) 
        newNode ( - 1이다. ); // 주문하지 방지 
        성 = 0 ; 
        N- = 0 , 
        S [N-] = - 1. ; // 국경 방지 
        페일 [ 0 ] = 1이다. ] 
    } 
    INT get_fail ( INT X) {
         while 회 (S [N-- LEN [X] - . 1! =에서 S [N-) = X 페일 [X]
         복귀 X; 
    } 
    무효화 추가를 ( INT C) { 
        C = C - ' ' , 
        S [ ++ N- = C;
         INT CUR = get_fail (최종) ; // 상동 서열에 의해 정합 위치 회문 스트링을 찾을 IF {(NE [CUR] [C]!) // 에는 팔린 드롬 서열이 없었을 경우에, 새로운 다른 자연 되돌아가 발생한 것을 나타 텍스트 문자열을 int로 newNode = (LEN [CUR] + 이제 2 ); // 새로운 노드가 
            실패 [지금] NE = [get_fail (실패 [CUR])] [C]; // 와 같은 자동 AC 기계에 대한 포인터를 설정하는 데 실패 점프 후에 불일치 
            NE [CUR] [C]가 =
        
             현재;
            NUM은 [현재]는 NUM [페일 [현재] +를 = 1이다. ] 
        } 
        최근 = NE [CUR] [C] 
        CNT [마지막] ++ ; 
    } 
    공극 count_cnt () {
          ( INT I = P- . 1 ; I> = 0 ; 난 ... ) { 
            CNT [페일 [I] + = CNT [I]; // 아버지 아들 축적 CNT 때문에 실패하면 [V] = u는 다음 u는 팔린 드롬 서열 서브 V이어야! 
        } 
    } 
} PAM; 

CHAR ST [MAXN]
 INT 의 main () { 
    는 scanf ( " %의 S " , ST)
     INT LEN =나 strlen (성); 
    pam.init (); 
    위한 ( int로 I = 0 ; I <렌 난 ++ ) { 
       pam.add (세인트 [I])를; 
    } 
    pam.count_cnt (); 
    LL 엄마 = 0 ;
    위한 ( int로 I = 2 ; 나는 <pam.p, 난이 ++ ) { 
        MA = 최대 ((LL) pam.len [I] * pam.cnt [I], MA); 
    } 
    COUT << MA << ENDL;
    반환  0 ; 
}

 

추천

출처www.cnblogs.com/philo-zhou/p/11502526.html