トピックへのリンク:https://www.luogu.org/problem/P3796
質問の意味:文字列に複数のモードとテキスト文字列、文字列マッチングは最高の数は数、およびこれらの文字列の出力パターンの数である必要があり。
分析:ノードへの接続点に戻ることができない、そのトライの下にのみ、その時点で、明らかにマッチングの数、ほとんど変化のようなAC_qurey機能を見て、私は失われたこれらのモード文字列の出力を見つけ、実際には、ああのような記録位置の配列と非常にシンプルかつ明白な、他のある、ないでしょう。。。。辞書ツリーノードは、最後にそれが単語のマーキング、ラベリングと秩序の終了前に一言だけ変更されます。
我々は再初期化時にクリーン機能は、彼らが側に使用されますどのくらいかわからないので、ACでのオートマトンは、初期化する必要がありますので、CNTが増加するたびに(つまり、新しい一つの縁があります)
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 const int型 MAXN = 1E6 + 10 。 const int型 INF = 0x3f3f3f3f 。 typedefの長い 長いLL。 #define meminf(A)のmemset(0x3fを、はsizeof(A)) の#define MEM0(A)のmemset(0、はsizeof(a)参照)。 構造体の結果{ int型NUM、POS。 } ANS [ 200 ]。 BOOL CMP(CONST結果と、CONST結果&B){ 場合(a.num == b.num)戻り a.pos < b.pos。 戻り a.num> ; b.num } 構造体ノード{ int型失敗; // ミスマッチポインタ失敗 INT VIS [ 26である ]; // 子ノードの位置、すなわち、26の文字がトライこと INTの終了; // もしテール・ノードが記録されている } AC [MAXN]; CHAR S [ 200である [] 100 ;] // 入力されたパターン文字列の 文字 SS [MAXN]; // 文字列の入力に使用 INT CNT = 0 ; // トライポインタ 無効クリーン(INT X){ MEM0(AC [X] .vis); AC [X] .END = 0; AC [X] .fail = 0 ; } ボイド INSERT(CHAR * S、int型のPOS){ int型 LEN = STRLEN(S); int型 =今0 ; // トライ現在のポインタ のための(int型 I = 0、I <LEN; Iは++ ){ // トライ木ない子ノード IF(AC [今] .vis [S [I] - [ A ' ] == 0)AC [今]を.vis [S [I] - [ ' ] ++ = CNT、クリーン(CNT); // 前にこれを使用する必要性への入力の組を複数、いずれかが必要曇りは、ノードCNT ++ = ACは現在[今]を.vis [S [I] - [ A ' ]; } AC [今] .END = POS; // マークノードは第1フラグであるワードの終わり、およびいくつかの単語です } ボイドget_fail(){ キュー < INT > QUE; のため(int型 I = 0 ;私は< 26であり、Iは++){ // 0に設定されている第2の層のポインタをフェイル IF(ACが[ 0 ] [I]を.vis! = 0 ) { AC [ACが[ 0 ] .vis [I]失敗= 0 ; que.push(AC [ 0 ] [I]を.vis)。 } } ながら(!Que.empty()) { int型 U = que.front(); que.pop() のために(int型私は= 0 ;私は< 26であり、Iは++ ){ IF(AC [U]は.vis [Iを]!= 0 ){ // 現在のノードの子ノードが存在する場合、ポインタは、ノードに現在のノードのポインタで失敗に対応する子ノードに子ノードが失敗する AC [AC [U] .vis [ I] ] = .fail ACは、[AC [U] .fail] .vis [I]; que.push(AC [U]は[I]を.vis); } そう AC [U]は.vis [I] = AC [ACを[ U] .fail] .vis [I]は、 // そうでない場合は、直接ノードに現在のノードのポインタのサブノードに対応する子ノードが存在しないことを指す失敗します } } } ボイド AC_query(CHAR *のS){ int型 LEN = STRLEN(S)。 int型になりました= 0 ; 以下のために(int型 iは= 0 ; iがLEN <; Iは++ ){ 今 = ACは、[今] [i]は[Sを- .vis ' ' ]。 用(INT ; T =!T =今0 tは=; {AC [T] .fail)を ANS [AC [T] .END] .num ++ 。 } } } int型のmain(){ int型N; 同時に (〜のscanf("Dの%」、& ))N- { IF N( - == 0)BREAK 、 CNT = 0 ; クリーン(0); // たびに、新しいエッジは、以前は、データ消去思い出す ために(INT I = 1 ; I <= N; I ++は){ ANS [I] .num = 0 ; ANS [I] .POS = I; scanfの(" %のS " 、S [I]); INSERT(S [I]、I)。 } AC [ 0 ] .fail = 0 ;終了フラグ // } get_fail(); // 求出失配指针 のscanf(" %sの" 、SS); AC_query(SS)。 ソート(ANS + 1、ANS + 1 + N、CMP)。 printf(" %d個の\ n "、ANS [ 1 ] .num)。 以下のために(int型 i = 1 ; iは= N <; iは++ ){ 場合(ANS [I] .num == ANS [ 1 ] .num){ のprintf(" %sのを\ n " 、S [ANS [i]は.POS ]); } 他に ブレーク。 } 戻り 0 。 }