[AC] 워드 오토마타

[링크] 표제

https://loj.ac/problem/10060

 

[제목] 이탈리아

신문을 읽는 사람은, 종이는 많은 단어로 구성되어있다. 그러나 그는 단어가 용지에 표시되는 여러 번 발견, 지금은 각 단어가 신문에 등장 얼마나 많은 시간을 알고 싶어요.

 

[설명]

AC 기계적으로 문제 3 템플릿하지만, 문자열 대상 레코드와 유사하게 중복되지 않습니다.

 

일정 이상의 뒤쪽에서 인덱스와 공통의 접미사 중첩 해당 위치를 사용. 그 이유는 단어가 나타난 경우, 해당 공통 접미사가 확실히 나타났다.

 

1 #INCLUDE <cstdio>
 2 #INCLUDE <알고리즘>
 3  사용  스페이스 성병;
4  CONST의  INT에서 N = 1005 ;
5  CONST의  INT의 M = + 1E6 (10) ;
6   S [N] [ 205 ];
7  INT 트리는 [M] [ 26 ] 실패 [M] 최종 [M], Sz를 [M];
8  INT의 Q [M], 헤드, 테일;
9  INT의 헤드 [M]에서 [M], NXT [M], CNT;
10  INT의 N, IDX = 1 ;
11  
12  공극 의 add_edge ( INTU, INT의 V);
(13)  보이드 DFS는 ( int로 U)를;
(14)  보이드 삽입 ( 문자 S [], INT 이드) {
 15      INT의 p = 1 ;
(16)      에 대한이 ( 값 int = 1이 0 , S [I]가, 난 ++ ) {
 17          INT의 t에서의 = S [I] - ' ' ;
18 의 경우 (! 트리는 [P] [t])
 19              트리는 [P] [t] = ++ IDX;
20          p = 트리는 [P] [t];
21          Sz를 [P] ++ ;
         22      }
 23      끝 [이드] = P를;
24  }
 25  무효 빌드 () {
 26      머리 = 1 , 테일 = 0 ;
(27)      에 대한이 ( 값 int = 1을 0 ; i가 < 26 ; i가 ++) 트리는 [ 0 ] [I] = 1 ;
28  
29      [++ 테일] Q = 1 ;
30 일      동안 (헤드 <= 테일) {
 31          INT U = Q [헤드 ++ ];
32           ( int로 = 1을 0 ; i가 < 26; 내가 ++ ) {
 33              INT =에 트리는 [U]를 [I];
34              의 경우 {(행)
 (35)                  [회] = 실패 트리는이 [실패 [U] [I];
(36)                  Q [++ 테일 = 하는 단계;
37              } 다른 {
 38                  트리는는 [U]가 [I]가 = 트리는이 [실패 [U] [I];
39              }
 40          }
 41      }
 42  }
 43  무효 쿼리 () {
 44  
(45)      / * 에 대해 (ⅰ = 1, p = 1 나타내는 int i가 <= N; 내가 ++) {
 46          p = 1;
47         대 (INT의 J = 0, S [I] [J] J ++) {
 48              INT의 t =에서 S [I] [J] - 'A';
49              p = 트리는 [P] [t];
50              Sz를 [P] ++;
51          }
 52      } * / 
53  
54       ( INT I = IDX; 나는> = 1 , 난 - ) {
 55  //         의 add_edge가 ([I, I 장애); 
56          Sz를가 [Q 실패 [I]] + = Sz를 [Q [I];
57      }
 58      // DFS (1); 
(59)      에 대한이 ( int로 I = 1 ; i가 N = <; 내가 ++ ) {
 60          의 printf (" % D \ 없음 " , Sz를 [종료 [I]);
61      }
 62  }
 63  INT 의 main ()
 64  {
 65      는 scanf ( " %의 D ' , N);
(66)      에 대한이 ( int로 I = 1 난 ++; i가 N = < {)
 (67)          는 scanf ( " %의 S " , S [I]);
68          삽입 (S [i]를, I);
(69)  
(70)          // 의 printf ( "### %의 ### \ n", S [I]); 
71      }
 72      빌드 ();
73      // 의 printf ( "@@@@ \ 없음"); 
(74)     질문();
75      반환  0 ;
76  }
 77  무효 DFS ( INT U) {
 78       ( int로 I = 헤드 [U] I, I = NXT [I]) {
 79          INT =로 에 [I];
80          DFS (로);
81          Sz를 [U] + = [회] Sz를;
82      }
 83  }
 84  보이드 의 add_edge ( INT U, INT V) {
 85      NXT [++ CNT = 헤드 [U];
86      헤드 [U] = CNT;
87      [CNT]에 =V;
88 }
겹치지의 수를 세어

 

추천

출처www.cnblogs.com/Osea/p/11366999.html