[Explanations] Bzoj3916

String \ (Hash \) .

I too dishes, has still not mastered \ (Hash \) , then come here to write a study notes.

\(Description\)

There are three friends like to play games together, \ (A \) Jun write a string \ (S, B \) Jun copy it over to give (T, C \) \ arbitrary position of the T-jun (inclusive ) insert a character get \ (U \) . now you got \ (U \) , you find \ (S. \)

\(Input\)

A first line number \ (N \) , represents \ (the U-\) length.

A second line character string \ (the U-\) , to ensure \ (the U-\) by capital letters

\(Output\)

Output line, if S does not exist, the output "NOT POSSIBLE". If \ (S \) is not unique, output "NOT UNIQUE". Otherwise output \ (S. \)

String \ (Hash \) , you can quickly do string matching. For example, selected from two sub-string matches a string, or to \ (the Hash \) a.

\ (Hash \) is a stochastic algorithm. We designed a \ (Hash \) function:

Provided string \ (C = c_1c_2 ... C_N \) , \ (K \) is the length of the string (before \ (K \) a)

Select two numbers \ (H B, \) , satisfies \ (B <H, \) B \ (and \) H $ coprime.

We have:

\(Hash(C,K)=Hash(C,K-1)*b+c_k\)

So, we complexity bottleneck in processing \ (b \) on.

Of the above function apart to write, that is:

Set \ (. 1-X m = \) ,

\(Hash(C)=(c_1*b^x+...+c_m*1) mod h\)

Pretreatment \ (b \) of power, can be recursive.

Consider (Hash \) \ issue of conflict.

In front of us took a modulus \ (h = Mod \) right. I wrote back \ (Mod \) .

Clearly, for any string \ (the Hash \) values are constant modulus \ (Mod \) a remainder of the sense lines can be considered in the interval $ [0, Mod-1] randomly distributed.

Consider several strings are not equal.

For the first series, with a \ (\ frac {Mod-1 } {Mod} \) probability.

If the first and second is not equal to, only \ (\ frac {Mod-2 } {Mod} \) probability.

And so on, all the strings are not equal probability is:

\ (\ Frac {Mod Mod {1}} * \ frac {Mod 2 Mod} {} * ... * \ frac {Mod i + 1} {For} \)

\ (I \) is the number of sub (enumeration) string.

When we modulus \ (1E9 \) , digital string \ (1e5 \) when the collision probability is:

\(0.006737160911819992\)

In so much data, it is clear collision probability is very high. How to increase the probability that it does not conflict?

When we choose modulus, found that the larger the modulus, the smaller the probability of conflict. Then we can use the \ (unsigned Long Long \) , natural overflow can be.

Also can double \ (Hash \) , but I was too dishes, no, I will not speak of it, in fact, even if it again \ (Hash \) and then calculate a few times, only \ (Hash \) values are all considered equal a successful match.

Consider a single \ (Hash \) .

This question, our idea is, to enumerate the breakpoint, then two sub-strings before and after the calculation of \ (Hash \) matches.

Take some substring \ (the Hash \) value, remember:

When an onset at \ (I \) , end point \ (J \) when (substring),

\(Hash=H[r]-H[l-1]*power[r-l+1]\)

Wherein \ (H \) array is to calculate the main string (the Hash \) \ calculated when.

This question is to pay attention to details. Heavy sentence, if there is the same as the previous answer, count as one. Unless the answer is different strings, considered multiple answers.

\(Code:\)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
typedef unsigned long long ull;
const int B=2333333;
const int H=1e9+9;
int n,vis,L;
ull power[2000010],h[2000010],last;
char s[2000010],a[2000010];
ull Get(int l,int r){return h[r]-h[l-1]*power[r-l+1];}
bool check(int pos){
    ull x,y,z;
    int flag=0;
    if(pos<L){
        x=Get(1,pos-1)*power[L-pos]+Get(pos+1,L);
        y=Get(L+1,n);
    }
    else if(pos>L){
        x=Get(1,L-1);
        y=Get(L,pos-1)*power[n-pos]+Get(pos+1,n);
    }
    else if(pos==L){
        x=Get(1,L-1);
        y=Get(L+1,n);
    }
    if(x==y){
        if(x==last)return 0;
        last=x;
        int top=0;
        if(pos<=L)
            for(int i=L+1;i<=n;++i)
                a[++top]=s[i];
        else
            for(int i=1;i<=L-1;++i)
                a[++top]=s[i];
        return true;
    }
    return 0;
}
int main(){
    scanf("%d",&n);
    scanf("%s",s+1);
    power[0]=1;
    if(n%2==0){
        printf("NOT POSSIBLE\n");
        return 0;
    }
    for(int i=1;i<=n;++i)
        power[i]=power[i-1]*B;
    for(int i=1;i<=n;++i)
        h[i]=h[i-1]*B+s[i];
    L=(n>>1)+1;
    for(int i=1;i<=n;++i){
        vis+=check(i);
        if(vis>1)break;
    }
    if(!vis){
        printf("NOT POSSIBLE\n");
        return 0;
    }
    else if(vis>1){
        printf("NOT UNIQUE\n");
        return 0;   
    }
    else puts(a+1);
    return 0;
} 

Guess you like

Origin www.cnblogs.com/h-lka/p/11317632.html