Static Hash table implementation

Static Hash table implementation


Wrote in a previous blog how to achieve near linear complexity "modulo hash table" storage implementation
link: https: //blog.csdn.net/qq_41418281/article/details/100045759


Introduced

  C ++ STL may be used to do the discretized map, a pre-set number is nlog (n), but each query is Log (n), is provided queries q, the complexity is O (min ( nlog (n), qlog (n ))), generally require discrete topic will not be great 1e6 n-hoisting, so long as the time when a large number of inquiries or groups of inputs, it is possible overtime.
  Of course, you can use STL as well unorder_map

Thinking

  Implemented using modulo hash table, the hash value of access to a certain element in O (1). How fast access? The number of assumptions required access to x, is not his hash value is x% n (n is the length of the array), it is not true, because of the need to consider several congruence, when congruence, we will him in the presence of a vacancy , so the offset phenomenon occurs. The first major difficulty lies in how to solve the problem of offset, so as to achieve the purpose of quick access. Exc array with a record in the hash value of the digital offset corresponding original array, the final hash value is exc [i] + x% n, implemented using a hash table is implemented disjoint-set, so nt = x% n, nnt = find (nt) to find a corresponding lower slot, the Hash [nnt] = x, it is found fill, reverse the process [i] = nnt-nt exc; second major difficulty is how to deal with duplicate numbers, different numbers of different hash values, the same number is a hash value, this map can be used to re-direct recording, there have been no increase in the new hash value, i.e. no mass, but when the access number, the offset also requires the use of a repeatable offset fishes, which incidentally also be present so the map at the last offset. Doing so still feel nlog (n), in fact, does not matter, pre-treatment required only once, back look is O (1), related to the discrete problem, the key is how to optimize search.

Code


int exc[maxn];//记录原数组每个数偏移量
int fa[maxn];//快速寻找下一个空位
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
int Hash[maxn];

void init()
{
    memset(exc,0,sizeof(exc));
    memset(Hash,-1,sizeof(Hash));
    for(int i=1; i<=n; i++)
        fa[i]=i;
}
int build_hash(int n,int ff[])
{
    map<int,pair<int,int> >mm;
    for(int i=1; i<=n; i++)
    {
        int t=ff[i];
        if(mm[t].first>=1)
        {
            exc[i]=mm[t].second;
            continue;
        }
        mm[t].first++;
        int nt=t%n;
        int nnt=find(nt);
        Hash[nnt]=t;
        exc[i]=nnt-nt;
        mm[t].second=nnt-nt;
        int nxt=nnt+1;
        if(nxt==n)
            nxt=0;
        fa[nnt]=find(nxt);
    }
}

int hash_find(int i,int x,int n)
{
    int nx=x%n;
    int len=exc[i];
    int now=nx+len;
    return now;
}

codeforces1208B

Topic connection: https: //codeforc.es/problemset/problem/1208/D

answer

Binary violence, discretized using the above implementation with Map timeout
2000 n is
the length of the log (n) between two partition
number in the array each number to be recorded, the number of times the number of sections is subtracted, it is determined whether or meet other number unique
interval violence search, but requires discrete, if the map, because it is the range query over complexity is nlog (n)
need to enumerate the interval so the n- the n- log (the n-) plus half the total complexity is O (n * n * log ( the n-) * log (the n-))
2000 * 2000 * log (2000) * log (2000) is about 484 million, will certainly be out, if using a static hash table, will be less complexity of a log (N), 1e7 can live

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 2005
#define maxm 2000005
#define INF 2147483647
#define mod  998244353
#define IOS ios::sync_with_stdio(false)

int ff[maxn];
int n;

int exc[maxn];//记录原数组每个数偏移量
int fa[maxn];//快速寻找下一个空位
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
int Hash[maxn];

void init()
{
    memset(exc,0,sizeof(exc));
    memset(Hash,-1,sizeof(Hash));
    for(int i=1; i<=n; i++)
        fa[i]=i;
}
int build_hash(int n,int ff[])
{
    map<int,pair<int,int> >mm;
    for(int i=1; i<=n; i++)
    {
        int t=ff[i];
        if(mm[t].first>=1)
        {
            exc[i]=mm[t].second;
            continue;
        }
        mm[t].first++;
        int nt=t%n;
        int nnt=find(nt);
        Hash[nnt]=t;
        exc[i]=nnt-nt;
        mm[t].second=nnt-nt;
        int nxt=nnt+1;
        if(nxt==n)
            nxt=0;
        fa[nnt]=find(nxt);
    }
}

int hash_find(int i,int x,int n)
{
    int nx=x%n;
    int len=exc[i];
    int now=nx+len;
    return now;
}

bool check(int k)
{
    int cc[maxn];
    memset(cc,0,sizeof(cc));
    for(int i=1; i<=n; i++)
        cc[hash_find(i,ff[i],n)]++;
    for(int i=1; i<=n-k+1; i++)
    {
        bool flag=true;
        int ct[maxn];
        for(int i=0; i<n; i++)
            ct[i]=cc[i];

        for(int j=i; j<=i+k-1; j++)
            ct[hash_find(j,ff[j],n)]--;

        for(int j=0; j<n; j++)
            if(ct[j]>=2)
            {
                flag=false;
                break;
            }
        if(flag)
            return true;
    }
    return false;
}

int main()
{
    IOS;
    cin>>n;
    for(int i=1; i<=n; i++)
        cin>>ff[i];

    init();
    build_hash(n,ff);
    /*for(int i=0; i<n; i++)
        cout<<Hash[i]<<" ";
    cout<<endl;
    for(int i=1; i<=n; i++)
    {
        cout<<hash_find(i,ff[i],n)<<" ";
    }
    cout<<endl;*/

    int L=0,R=n;
    while(L<R)
    {
        int mid=(L+R)/2;
        if(check(mid))R=mid;
        else
            L=mid+1;
        //cout<<"mid="<<mid<<" "<<L<<" "<<R<<" "<<endl;
    }
    cout<<L;
    return 0;
}


Published 41 original articles · won praise 2 · Views 1240

Guess you like

Origin blog.csdn.net/qq_41418281/article/details/100641370