交流自動機は、ジャンプ・ポインタの木によって確立された問い合わせを失敗--cf963D

ソリューションは、失敗したACオートマトン暴力ポインタジャンプを最適化するために、実際には、怖い見えました。

この問題解析の複雑さに加えて、それは非常に価値があるの学習

/ * 
文字列sの母が与えられると、与えられたnが(K、M)を得るように求め
ているが、サブストリングS、T、Mであり、tにおけるサブストリングとして表示されるように、Tは、最小の長さを決定し、各チャレンジのためにm回は、

複数の文字列の交流オートマトンを確立し、その後、一致するよ、すべてのクエリでの出現位置ベクトルは維持され
、kは、各更新クエリの応答に対応する

複雑性を確保するために:ジャンプは暴力を失敗ジャンプアップではありません、直接で前のクエリにジャンプを指すポインタである必要があり
、クエリベクトルが更新された新しい値にしましょうたびにジャンプアップな
ので、ほとんどのsqrt(n)が異なるクエリ文字列の長さ、あたりをS [i]にのみSQRT(n)の数に一致する文字列の末尾であることが、
即ち、nsqrt(n)の時間失敗ツリーにジャンプ
* / 
の#include <ビット/ STDC ++ H.>
 使用して 名前空間STDと、
 の#define N 200005 構造体のクエリ{ 
    ベクトル < INT > POS;
     INT K、LEN; 
} Q [N]; CHAR S [N]、BUF [N];
 int型N-、構造体トライ{
    




INT NXT [N] [ 26 ]、失敗[N]、ID [N]は、[N]を事前。
    int型の根、L。
    int型newnode(){ 
        memsetの(NXT [L]、 - 1はsizeof NXT [L])。
        ID [L] = 0 ;
        リターン L ++ ; 
    } 
    ボイドのinit(){L = 0 ;ルート= newnode();}
     ボイドインサート(CHAR BUF []、int型のID){
         int型 LEN = STRLEN(BUF)。
        int型になりました= ルート。
        以下のためのint型私は=0 ; iがLEN <; iは++ ){
             場合(NXT [今] [BUF [I] - ' ' ] == - 1 
                NXT [今] [BUF [I] - [ A ' ] = newnode()。 = NXT [今] [BUF [I] - ' ' ]。
        } 
        ID [今] = ID。
    } ボイドビルド(){ 
        キュー < INT > Q。
        【ルート】フェイル = ルートと、
        以下のためにint型 = Iを0 ; iは< 26
    ; Iは++ IF - (NXT [ルート] [I] == 1 
                NXT [ルート] [I]は = 、ルートを
             { 
                失敗[NXT [ルート] [I] = 根; 
                q.push(NXT [ルート] [I]); 
            } 
        [ルート]予備 = 0 ; 
        
        一方(q.size()){
             int型今q.front =(); q.pop(); // ザは現在十分に確立失敗この場合、
            IF(ID ![失敗[今]] = 0//が所在問合せ見つける 
                前[今] = 失敗[今]を、
             それ以外の 
                事前[今]= 事前[今] [失敗]。
            
            以下のためにint型 i = 0 ; iは< 26 ; I ++ 場合(NXTは、[今] [I] == - 1 
                    NXTは、[今] [i]は = NXT [失敗今] [I];
                { 
                    [NXT [今] [I]失敗 = NXTを[I] [今] [失敗]。
                    q.push(NXT [今] [I])。
                } 
        } 
    } 
    
    ボイドクエリ(CHAR *のS){
         int型 LEN = STRLEN(S)。
        int型になりました= ルート。
        以下のためにint型 i = 0 ; iがLEN <; iは++ ){  = NXTを[今] [S [I] - ' ' ]。
            // 通过事前向上跳int型のp = 今;
            一方、(P){ 
                。Q [ID [P]] pos.push_back(I)。
                P = プレ[P]。
            } 
        } 
    } 
} AC。INT メイン(){ 
    ac.init()。
    scanf関数(" %sの" 、S); 
    cinを >> N;
    以下のためのint型私は=
            
        

1 ; iが<= N; iが++ ){ 
        scanf関数(" %D%S "、&Q [I]・K、BUF)。
        Q [i]は.LENの =のSTRLEN(BUF)。
        ac.insert(BUF、I); 
    } 
    ac.build()。
    ac.query(S); 

// ため(; I <= ac.L I ++はI = 1 INT)
 //     COUT << ac.pre [I] <<」「。

    // 处理每个询问
    ためint型 I = 1 ; I <= N; iは++ ){
 // COUT << Q [i]を.pos.size()<< "\ nを"。
        もし(Q [i]が.pos.size()< Q [I]・K){ 
            プット(" -1 ")。
        
         INT ANS = 0x3f3f3f3f int型 Jは= Q [-i]に対してkは1 ; jが<[-i] possize()へのQ ++、jは{)
            ANS =分(AT [-i] POSに、Q ANS -q [-i] [jがあります] POS [JQ [-i]・K +、1 ] +、[-i] LENにQ)。
        } 
        COUT << << ANS ' を\ n ' 
    } 
} 
/ * 

Aaabbbbaaabababab 
27と、
2 aaabbbbaaaba 
2 baaabab 
1 abbbbaaabab 
1 aabbbbaaabab 
6又は
1 aaabbbbaaabababab 
2 AABA 
2 abbbba 
5「AA 
2 aaabbbb 
2 abababa
ABA 3 
2 baaa 
2 bbaaababa 
1 aaabab 
1 ABBB 
1 bbbbaaabababa 
1 baaab 
1 abbbbaaabababa 
1 aaababa 
1 ABABAB 
2 ABB 
2 baaabababa 
1 bbaaabababa 
2 aaabb 
1 ABABABAB 
4 BAB 



* /

 

おすすめ

転載: www.cnblogs.com/zsben991126/p/11701240.html