ACロス自動マシンテンプレートバレーP3796

トピックへのリンク: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] .nu​​m ++ 
        } 
    } 
} int型のmain(){
     int型N;
    同時に

(〜のscanf("Dの%、& ))N- 
    { 
    IF N( - == 0BREAK 
    CNT = 0 ; 
    クリーン(0); // たびに、新しいエッジは、以前は、データ消去思い出す
    ためにINT I = 1 ; I <= N; I ++は){ 
        ANS [I] .nu​​m = 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 ] .nu​​m)。
    以下のためにint型 i = 1 ; iは= N <; iは++ ){
         場合(ANS [I] .nu​​m == ANS [ 1 ] .nu​​m){ 
            のprintf(" %sのを\ n " 、S [ANS [i]は.POS ]); 
        } 
        他に ブレーク
    } 
    戻り 0 
}

 

おすすめ

転載: www.cnblogs.com/qingjiuling/p/11375228.html