Cod sursa(job #912268)

Utilizator maritimCristian Lambru maritim Data 12 martie 2013 11:07:08
Problema Hashuri Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 5.95 kb
#include<iostream>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<fstream>
#include<ctype.h>
using namespace std;
  
class CuckooHash
{
    private:
        int hashA1,hashA2,hashB1,hashB2;
        int M1,M2,size,limit;
        int uninserted,prime;
        int *Hash1,*Hash2;
        int *aux;
  
        void makeSizes(void);
        int hashFunction1(int x);
        int hashFunction2(int x);
        void remakeFunctions(void);
        int reinsert(int x);
        int rehash(void);
        int insertTry(int x);
  
    public:
        CuckooHash(void);
        CuckooHash(int M1,int M2);
        int insert(int x);
        int remove(int x);
        int find(int x);
};
  
CuckooHash::CuckooHash(void)
{
    srand(time(NULL));
  
    this->M1 = 1000003;
    this->M2 = 1000033;
  
    prime = 1000000009;
  
    Hash1 = new int[1200000];
    Hash2 = new int[1200000];
    aux = new int[1000000];
  
    remakeFunctions();
}
  
CuckooHash::CuckooHash(int M1,int M2)
{
    srand(time(NULL));
 
    this->M1 = M1;
    this->M2 = M2;
  
    prime = 1000000009;
  
    Hash1 = new int[1200000];
    Hash2 = new int[1200000];
    aux = new int[1000000];
  
    remakeFunctions();
}
  
int CuckooHash::hashFunction1(int x)
{
    return ((1LL*hashA1*x+hashA2)%prime)%M1;
}
  
int CuckooHash::hashFunction2(int x)
{
    return ((1LL*hashB2*x+hashB1)%prime)%M2;
}
  
void CuckooHash::remakeFunctions(void)
{
    hashA1 = rand()%prime;
    hashA2 = rand()%prime;
    hashB1 = rand()%prime;
    hashB2 = rand()%prime;
}
  
void CuckooHash::makeSizes(void)
{
    this->M1 = 1000011 + rand()%666013;
    this->M2 = 1000011 + rand()%666013;
  
    this->M1 += 1-(this->M1 & 1);
    this->M2 += 1-(this->M2 & 1);
  
}
  
inline int CuckooHash::rehash(void)
{
    /*Functia de rehash. Se iau toate elementele
    din hash si se pastreaza separat. Se goleste
    hashul si se incearca reinserarea fiecarui
    element folosind functii de hash diferite.*/
 
    int limit = -1;
 
    aux[++limit] = uninserted;
  
    for(int i=0;i<M1;i++)
        if(Hash1[i])
            aux[++limit] = Hash1[i];
  
    for(int i=0;i<M2;i++)
        if(Hash2[i])
            aux[++limit] = Hash2[i];
  
    int i = limit;
  
    for(;;)
    {
       for(int j=0;j<=limit;j++)
            remove(aux[j]);
  
        remakeFunctions();
  
        for(i=0;i<=limit;i++)
            if(!insertTry(aux[i]))
                break;
  
        if(i == limit+1)
        {
            return 1;
        }
    }
 
    return 0;
}
  
inline int CuckooHash::reinsert(int x)
{
    /*Functia care incearca sa reinsereze
    elementul x. Inserarea se face alternativ
    intre cei doi vectori. Daca pozitia pe care
    incearca sa insereze elementul x este o cupata
    se elimina elementul respectiv, se atribuie
    pozitiei valoarea lui x si se apeleaza
    recursiv functia reinsert pentru valoarea
    eliminata.*/
 
    int hash_funct2 = hashFunction2(x),
        hash_funct1 = hashFunction1(x);
  
    if(size == 0)
    {
        uninserted = x;
        return 0;
    }
  
    if(size & 1)
    {
        if(Hash1[hash_funct1])
        {
            int y = Hash1[hash_funct1];
            Hash1[hash_funct1] = x;
            -- size;
            return reinsert(y);
        }
        else if(size & 1)
        {
            Hash1[hash_funct1] = x;
            return 1;
        }
    }
    else
    {
        if(Hash2[hash_funct2])
        {
            int y = Hash2[hash_funct2];
            Hash2[hash_funct2] = x;
            -- size;
            return reinsert(y);
        }
        else
        {
            Hash2[hash_funct2] = x;
            return 1;
        }
    }
 
    return 0;
}
  
inline int CuckooHash::insertTry(int x)
{
    /*Functia care verifica daca un element
    poate fi inserat in Hash. Daca poate sa il
    insereze, il insereaza, iar daca nu, pastreaza
    ultimul element neinserat in variabila privata
    "inserted"*/
 
    int hash_funct1 = hashFunction1(x);
  
    if(find(x))
    {
        return 1;
    }
  
    if(Hash1[hash_funct1])
    {
        int y = Hash1[hash_funct1];
        Hash1[hash_funct1] = x;
        size = 20;
        return reinsert(y);
    }
    else
    {
        Hash1[hash_funct1] = x;
        return 1;
    }
}
  
inline int CuckooHash::insert(int x)
{
    /*Functia publica de insert care
    incearca sa insereze valoarea x
    si daca nu reuseste apeleaza functia
    rehash.*/
 
    if(!insertTry(x))
    {
        rehash();
    }
  
    return 1;
}
  
inline int CuckooHash::remove(int x)
{
    /*Daca exista valoarea x in hash
    se elimina, atribuindu-se pozitiei
    valoarea 0*/
 
    int hash_funct1 = hashFunction1(x);
    int hash_funct2 = hashFunction2(x);
  
    if(Hash1[hash_funct1] == x)
    {
        Hash1[hash_funct1] = 0;
        return 1;
    }
    else if(Hash2[hash_funct2] == x)
    {
        Hash2[hash_funct2] = 0;
        return 1;
    }
  
    return -1;
}
  
inline int CuckooHash::find(int x)
{
    /*Se cauta valoarea x in hash.
    Daca valoarea nu se gaseste in niciunul
    dintre cei 2 vectori inseamna ca nu exista
    in hash!*/
 
    int hash_funct1 = hashFunction1(x);
    int hash_funct2 = hashFunction2(x);
  
    if(Hash1[hash_funct1] == x)
    {
        return 1;
    }
    else if(Hash2[hash_funct2] == x)
    {
        return 1;
    }
  
    return 0;
}
  
int main()
{
    ifstream f("hashuri.in");
    ofstream g("hashuri.out");
  
    int N,op,a;
  
    CuckooHash Hash;
  
    f >> N;
  
    for(int i=1;i<=N;i++)
    {
        f >> op >> a;
          
        switch(op)
        {
            case 1 : Hash.insert(a);
                break;
            case 2 : Hash.remove(a);
                break;
            case 3 : g << Hash.find(a) << "\n";
        }
    }
  
    f.close();
    g.close();
}