ACは、複数の文字列照合オートマトンを扱う--cf1202E

シリコンSJ +中間カット点を有し、我々はT上の切削点Iを列挙し、それをt [i]は、必要な数のSI最後の文字がtに一致させることができるように、[I + 1]の先頭文字としてSJをどのくらいの時間を一致させることができます

次いで、AC付きシーケンスS Nは、ロボット、自動抗ビルドマシンとSUM []アレイレコードTで一度正および負のマッチングtのそれぞれを構築[i]は、最後の文字列マッチングの数とすることができるように

注意:和アレーを求めている場合は、暴力は明らかにトンを失敗ジャンプします、アカウントに統計的なジャンプを服用すると、文字列のサフィックスと一致しないので、我々が構築したときに、あなたが失敗したこと置くことができる過程で、今末尾に追加することができますポインタを失敗しますこれ暴力的なジャンプが失敗避け、終わります

#include <ビット/ STDC ++ H>
 使用して 名前空間STDを、
#define N 200005 構造体トライ{
     INT NXT [N] [ 26 ]、失敗[N]、エンド[N]。
    int型の根、L。
    int型newnode(){ 
        memsetの(NXT [L]、 - 1はsizeof NXT [L])。
        端[L] = 0 ;
        リターン L ++ ; 
    } ボイドのinit(){ 
        L ++ 
        ルート = newnode()。
    } ボイドインサート(CHAR


    
    BUF []){
         int型 LEN = STRLEN(BUF + 1 )。
        int型になりました= ルート。
        以下のためにint型 i = 1 ; iは= LEN <; iは++ ){
             場合(NXT [今] [BUF [I] - ' ' ] == - 1 
                NXT [今] [BUF [I] - [ A ' ] = newnode()。 = NXT [今] [BUF [I] - ' ' ]。
        } 
        [今]終了 ++ 
    } ボイドビルド(){ 
        キュー
    < 整数 > Q; 
        【ルート】フェイル = ルートと、
        以下のためにint型 i = 0 ; iは< 26 ; iは++ 場合(NXT [ルート] [I] == - 1 
                NXT [ルート] [I] = 根。
            { 
                [NXT [ルート] [I]失敗 = ルートと、
                q.push(NXT [ルート] [I])。
            } 
        ながら(q.size()){
             int型 =今)(q.front。
            q.pop(); 
            以下のためのint型 I = 0;私は< 26 ; iが++ 場合(NXT [今] [I] == - 1 
                    NXT [今] [I] = NXT [I] [今] [失敗します]。
                { 
                    [NXT [今] [I]失敗 = NXTを[I] [今] [失敗]。
                    エンド[NXT [今] [I] + = 終わり[NXT [今] [i]と[失敗]。
                    q.push(NXT [今] [I])。
                } 
        } 
    } 
    int型の和[N]。
    INTクエリ(CHAR BUF []){
         int型 LEN = STRLEN(BUF + 1 )。
        int型になりました=ルート;
        以下のためにint型 i = 1 ; iは= LEN <; iは++ ){  = NXT [今] [BUF [I] - ' ' ]。
            和[I] + = 終わり[今]。
        } 
    } 
}。チャーBUF [N]、T [N]。
トライT1、T2。int型のn;
ボイドリザーブ(CHAR S []){
     int型 I = 1、J =用のSTRLEN(S + 1 )。
    一方(iは< j)を{ 
        スワップ(S [i]は、S [J])。++ I、 - J。
    } 
} int型



        

メイン(){ 
    t1.init()。
    t2.init();    
    scanf関数(" %sの%のD "、T + 1、&N)
    以下のためにint型私= 1 ; iが<= N; iが++ ){ 
        scanf関数(" %sの"、BUF + 1 )。
        t1.insert(BUF)。
        リザーブ(BUF)。
        t2.insert(BUF)。
    } 
    t1.build()。
    t2.build(); 
    t1.query(T)。
    リザーブ(T)。
    t2.query(T)。
    
    INT LEN = STRLEN(T + 1 )。
    長い 長い ANS =0 ;
    int型 I = 0 ; iがLEN <; Iは++ 
        ANS + =(長い 長い)t1.sum [I] * t2.sum [len- I]。
    coutの << ANS << ' \ nを' ; 
}

 

おすすめ

転載: www.cnblogs.com/zsben991126/p/11518657.html
おすすめ