羅区--P3808 [テンプレート] AC自動機(「偽」簡易版)

あなたはこの問題をうまくしたい場合は、最初の二つの知識のポイントを理解する必要があります。

1、木構造辞書

2、KMPアルゴリズム(すなわち、コンフィギュレーション・ポインタを失敗)

トライでは、この兄を見ることができます:

https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html

KMPのために、あなたはこの兄を見ることができます:

https://www.cnblogs.com/SYCstudio/p/7194315.html#4255259  (強く推奨!!!!)

ステップ:(最初の2つのステップのためのコードが必要オートマトンACです)

図1に示すように、提供されたパターン文字列のトライ構造を使用して

図2に示すように、ポインタの構成、すなわち、現在のノードのポインタが失敗=親ノードをフェイル、フェイル同じ子ノードを指摘指摘。値のためのアイデアを借りて、ポインタのFIFOキューキューに失敗(ここでは困難であり、コメント欄を理解しないでください)に定義されます

数のANSを返す質問コンストラクタクエリ機能の意味に従って3、

ACコード:

#include <ビット/ STDC ++ H.>
 使用して 名前空間STD; 
typedefの長い ロングLL;
 のconst  int型 MAXN = 1E6の+ 5 ;
 CHAR T [MAXN]、S [MAXN];
 構造体ツリー
{ 
    int型失敗; // ミスマッチポインタ
    INT息子[ 26 ]; // ノード26までの子ノードを有している
    INT NUM; //は、このノードの最後としてマーク 
} DFA [MAXN]; // トライ
INT CNT = 0 ;
 空隙を作る(文字列S)
{ 
    int型 =今0; // トライ現在のポインタ
    のためのint型 I = 0 ;私は(s.lengthを<); ++ I)
    { 
        IF(DFA [今] .son [S [I] - [ A ' ] == 0/ / 木の子ノードではありません 
            DFA [今] .son [S [I] - ' A ' ] = CNT ++; // ノードを追加し 
        、今DFA = [今] .son [S [I] - " ' ]; // 下方構成    } 
    DFAは、[今] .nu​​m + = 1 ; // 終了タグワード}
 ボイド Get_fail()// コンストラクタポインタフェイル


{ 
    キュー < INT > Q;
     のためのint型 I = 0 ;私は< 26であり ; ++ I)
    { 
        IF(DFA [ 0!] .Son [I] = 0 
        { 
            DFA [DFA [ 0 ] .son [I] ] .fail = 0 ; // ルートノードを指し、第二層 
            Q.push(DFA [ 0 ] .son [I]); // キューに押し込む
        } 
    } 
    ながら(!Q.empty())
    { 
        int型 U = Q.front(); 
        Q.pop(); 
        のためにINT I = 0 ;私は< 26である ;)I ++は   // バック層
        {
             IF(DFA [U] .son [I] =!0// このノードが存在する場合
            、{ 
                DFA [DFA [U] .son [ I]]は失敗。 = DFA [DFA [U] .fail] .son [I]; // ノードの親ノードに失敗の値に対応する同一の子ノード 
                Q.push(DFA [U] .son [ I]); //は、キューに入れられ
            }
              // このノードが存在しない場合
            { 
                DFA [U] .son [I] = DFA [DFA [U] .fail] .son [I]は、   // 現在のノードの子ノード現在のノードの子ノードへのポイント失敗
            } 
        } 
    }
} 
int型の照会(チャー *のS)
{ 
    int型 LEN = STRLEN(S)。
    int型になりました= 0、ANS = 0 ;
    以下のためにint型 i = 0 ; iがLEN <; ++ I)
    {  = DFA [今] .sonの[S [I] - ' ' ]。
        INT ;!T = T =今0! - && DFA [今] .nu​​m = 1 ; ++ T)
            { 場合(DFA [今] .nu​​m> 0// 表示存在结尾 
                    ANS + =
                DFA [今] .nu​​m。
                 DFA [T] .nu​​m = - 1// 标记已访问过
            } 
        } 
    戻りANS; 
} 


int型のmain()
{ 
    int型N; 
    scanf関数(" %のD "、&N)
    以下のためにint型 i = 0 ; iがn <; iは++ 
    { 
        scanf関数(" %sの" 、T); 
        (t)を構築します。
    } 
    Get_fail()。
    scanf関数(" %sの" 、S);
    int型 ANS =クエリ(複数可)。
    printf(" %d個の\ n " 、ANS)。
    リターン 0 ; 
}

、怠惰な私を許し、理解することは困難ACオートマトンは私たちに十分な解像度を与えていないが、我々は、私はプライベートエリアをコメントすることができ、問題を持って、私はそれらを答えてみます!

 

おすすめ

転載: www.cnblogs.com/acmer-hmin/p/11761622.html