LOJ2823三人の友 - クエリ文字列のハッシュ値

コンセプト

クエリ文字列のハッシュ値

我々は、それはいくつかの非常に便利な性質を持っているので、通常は例えば、それは接頭辞と同様の性質を持っている、バイナリのハッシュをハッシュさについて話しています。

時間ベース+ S [i]の時間$ \ [I] = [I-1] [i]は進$ベース$の$を、その後明らかに$ H列は、ハッシュ値のプレフィックス$ Hと呼ばれると仮定する。

ノートの$ P [i]は$は、その後、我々はO(1)$文字列のハッシュ値を取得することができる$、$ $ I $ $ベースパワーです。

typedefの符号なしの長い 長いULL。
ULL get_hash(int型 L、INT R){
     戻り H [R] - H [1 - 1 ] * P [R - L + 1 ]。
}

前記は、$ P [R-L + 1] $左の$ R-L + 1 $ビットに対応乗じ。

同様に、我々はO(1)$の文字を削除するには、文字列のハッシュ値を取得$することができます。

ULLのget_s(int型 L、int型の R、int型X){
     戻り get_hash(L、X - 1)* P [R - X] + get_hash(X + 1 、R)。
}

質問の意味:文字列$ Sの$を考えるには、$ S $文字列は、文字列$ U $を与えるために$ T $の文字を挿入し、文字列$ T $を取得するには、最初の時間をコピーします。現在の$ S $を再構築するために必要な文字列の$ U $を、与えられています。

分析:

列挙各位置は、残りの二つは、ハッシュ値に決定されたものによれば、同じ文字列でなければなりません。

#include <ビット/ STDC ++ H>
 使用して 名前空間STDを、

typedefの長い 長いLL。
typedefの符号なしの長い 長いULL。
CONST ULLの基地 = 233 const  int型 MAXN = 2000000 + 10 
ULL H [MAXN]、P [MAXN]。
チャーS [MAXN]。
int型のlen; 

無効のinit()
{ 
    LL ANS = 0 以下のためにint型私= 0 ;私がlen <;私は++  
    {
        ANS=(ANS * 基底)+ (ULL)S [i]は、
        H [I] =のANS。
    } 
    P [ 0 ] = 1 以下のためにint型 i = 1 ; iは= LEN <; iは++ 
    { 
        P [I] = P [I- 1 ] * 基地; 
    } 
} 

インラインLL GETHASH(INT L、INT R)
{ 
    戻り H [R] - H [1- 1 ] * Pの[R-L + 1 ]。
} 

インラインLLデル(int型 L、INT R、INT X)
{ 
    IF(X <L || X> R&LT)
         を返すGETHASH(L、R&LT);
     戻り、X-をGETHASH(Lを1)* P [RX] + GETHASH(Xの+ 1 、R&LT); 
} 

インラインint型のチェック(INT X)// 正当性チェックXビット除去
{
     IF = LEN /(X < 2デル(&& 0、lenの1、X)==デル(0、LEN >> 1、X)* P [LEN >> 1 ] +デル(0、LEN >> 1 、X))
         リターン 1。;
      IF(X> LEN / 2&&デル(0、len- 1、X)==デル(0、(LEN >> 1) - 1、X)* P [LEN >> 1 ] +デル(0、(LEN >> 1) - 1 、X ))
         リターン 1 それ以外
        の戻り 0 ; 
} 

int型のmain()
{ 
    scanf関数(" %のD "、およびLEN)。
    scanf関数(" %sの" 、S); 
    その中に(); 
    int型 CNT = 0 ;
    int型 II = - 1 ; 
    ; LL NUM 
    ためint型 I = 0 ; IはLEN <Iは++ 
    { 
        IF ((I)を確認)
        { 
            CNT ++ ;
             IF( - II == 1 
            { 
                II = I; 
                NUM =デル(0、LEN - 1 、I); 
            } 
            
            { 
                IF(DEL(0、LEN 1、II)デル==(0、LEN 1。 私は))   // 同じ文字列であってもよいです
                    cnt-- ; 
            } 
        } 
        もし(CNT == 2 
        { 
            のprintf(" NOT UNIQUEの\ n " );
            リターン 0 ; 
        } 
    } 
    もし(CNT == 1 
    { 
        int型、M = 0 INT J = 0 ; J <LEN; J ++)    // 输出结果
        {
             場合(jは== II)を
                 続け
            printf("%のC "S [J]); 
            M ++ ;
             もし(m個の==(len- 1)/ 2 ブレーク; 
        } 
        のprintf(" の\ n " ); 
    } 
    もし(CNT == 0 
    { 
        のprintf(" 不可能\ nを" ); 
    } 
    の戻り 0 ; 
}

 

 

参考リンク:https://loj.ac/submission/576434

 

おすすめ

転載: www.cnblogs.com/lfri/p/11375342.html