Cod sursa(job #936630)

Utilizator brainwashed20Alexandru Gherghe brainwashed20 Data 7 aprilie 2013 23:28:46
Problema Hashuri Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 7.51 kb
#include<fstream>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<iostream>
#include<vector>

using namespace std;

class hash_function {

    private:

    int a, b, prime, size;

    public:

    void generate(int, int);
    int calculate(int);
    int calculate(float);
    int calculate(double);
    int calculate(string);
};

void hash_function::generate(int dim, int p) {

    prime = p;
    size = dim;

    a = rand() % size;
    b = rand() % size;
}

int hash_function::calculate(int val) {
    return(((long long)a * (long long)val + (long long)b) % (long long)prime) % (long long)size;
}

int hash_function::calculate(float val) {

    int key;
    float number, fractpart, intpart, mult_magic = 0.618034;

    number = val*mult_magic;
    fractpart = modf(number, &intpart);
    key = (((long long)a * (long long)fractpart + (long long)b * (long long)intpart) % (long long)prime) % (long long)size;

    return key;
}

int hash_function::calculate(double val) {

    int key;
    double number, fractpart, intpart, mult_magic = 0.618034;

    number = val*mult_magic;
    fractpart = modf(number, &intpart);
    key = (((long long)a * (long long)fractpart + (long long)b * (long long)intpart) % (long long)prime) % (long long)size;

    return key;
}

int hash_function::calculate(string str) {

    unsigned InitialFNV = 2166136261U, key;
    int FNVMultiple = 16777619, dim, i;

    dim = str.length();
    key = InitialFNV;
    for(i = 0; i<dim; i++) {
        key = key ^ (str[i]);
        key = key * FNVMultiple;
    }
    key = (((long long)a * (long long)key + (long long)b) % (long long)prime) % (long long)size;

    return key;
}

/* ------------------------------------------------------------------------------------------- */

template<class T>
class cockooHash {

    private:

    ifstream f;
    ofstream g;
    T *H1, *H2;
    int prime, size, maxsteps;
    bool *viz1, *viz2;
    string input, output;
    hash_function func1, func2;

    public:

    cockooHash<T>(int, string, string);
    bool remake_hash();

    bool operator[](T);
    void operator+=(T);
    void operator-=(T);
};

template<class T>
void cockooHash<T>::operator-=(T val) {

    int poz1 = func1.calculate(val);
    int poz2 = func2.calculate(val);

    if(H1[poz1] == val && viz1[poz1] == true) {
        viz1[poz1] = false;
        return;
    }

    if(H2[poz2] == val && viz2[poz2] == true) {
        viz2[poz2] = false;
        return;
    }
}

template<class T>
void cockooHash<T>::operator+=(T val) {

    int i, poz1, poz2;
    T x;

    x = val;
    poz1 = func1.calculate(x);
    poz2 = func2.calculate(x);

    //cout<<val<<" "<<poz1<<" "<<poz2<<" "<<size<<" "<<prime<<"\n\n";

    if(viz1[poz1] == false) {
        H1[poz1] = x;
        viz1[poz1] = true;
        return;
    }

    for(i=0; i<maxsteps; i+=2) {
        if(viz2[poz2] == false) {
            H2[poz2] = x;
            viz2[poz2] = true;
            return;
        }

        swap(x, H2[poz2]);
        poz1 = func1.calculate(x);
        poz2 = func2.calculate(x);

        if(viz1[poz1] == false) {
            H1[poz1] = x;
            viz1[poz1] = true;
            return;
        }

        swap(x, H1[poz1]);
        poz1 = func1.calculate(x);
        poz2 = func2.calculate(x);
    }

    remake_hash();
}

template<class T>
bool cockooHash<T>::remake_hash() {

    int Q, op, val;

    f.open(input.c_str());
    g.open(output.c_str());

    f>>Q;
    while(Q--) {
        f>>op>>val;
        if(op == 1) {
            if(!(*this)[val])
                *this += val;
        }
        if(op == 2) {
            if((*this)[val])
                *this -= val;
        }
        if(op == 3)
            g<<(*this)[val]<<"\n";
    }

    f.close();
    g.close();

    return true;
}

template<class T>
cockooHash<T>::cockooHash(int dim, string infile, string outfile) {

    size = dim;
    maxsteps = (int)log2(size);
    prime = 1000000009;
    input = infile;
    output = outfile;

    H1 = new T[size];
    H2 = new T[size];

    viz1 = new bool[size];
    viz2 = new bool[size];
    memset(viz1, 0, sizeof(viz1));
    memset(viz2, 0, sizeof(viz1));

    func1.generate(size, prime);
    func2.generate(size, prime);
}

template<class T>
bool cockooHash<T>::operator[](T val) {

    int poz1 = func1.calculate(val);
    int poz2 = func2.calculate(val);

    //cout<<val<<" "<<poz1<<" "<<poz2<<" "<<size<<" "<<prime<<"\n\n";

    if(H1[poz1] == val && viz1[poz1] == true)
        return true;
    if(H2[poz2] == val && viz2[poz2] == true)
        return true;

    return false;
}

/* ------------------------------------------------------------------------------------------- */

template<class T>
class doublehash {

    private:

    ifstream f;
    ofstream g;

    vector<T> *H1, *H2;
    int prime, size;
    string input, output;
    hash_function func1, func2;

    public:

    doublehash<T>(int, string, string);
    bool remake_hash();

    bool operator[](T);
    void operator+=(T);
    void operator-=(T);
};

template<class T>
doublehash<T>::doublehash(int dim, string infile, string outfile) {

    size = dim;
    prime = 1000000009;
    input = infile;
    output = outfile;

    H1 = new vector<T>[size];
    H2 = new vector<T>[size];

    func1.generate(size, prime);
    func2.generate(size, prime);
}

template<class T>
bool doublehash<T>::operator[](T val) {

    int poz1 = func1.calculate(val);
    int poz2 = func2.calculate(val);

    typename vector<T>::iterator it;

    for(it=H1[poz1].begin(); it!=H1[poz1].end(); ++it)
        if(*it == val)
            return true;

    for(it=H1[poz2].begin(); it!=H1[poz2].end(); ++it)
        if(*it == val)
            return true;

    return false;
}

template<class T>
void doublehash<T>::operator+=(T val) {

    if((*this)[val])
        return;

    int poz1 = func1.calculate(val);
    int poz2 = func2.calculate(val);

    if(H1[poz1].size() > H2[poz2].size())
        H2[poz2].push_back(val);
    else
        H1[poz1].push_back(val);
}

template<class T>
void doublehash<T>::operator-=(T val) {

    if(!(*this)[val])
        return;

    int poz1 = func1.calculate(val);
    int poz2 = func2.calculate(val);

    typename vector<T>::iterator it;

    for(it=H1[poz1].begin(); it!=H1[poz1].end(); ++it)
        if(*it == val) {
            H1[poz1].erase(it);
            return;
        }

    for(it=H1[poz2].begin(); it!=H1[poz2].end(); ++it)
        if(*it == val) {
            H2[poz2].erase(it);
            return;
        }
}

template<class T>
bool doublehash<T>::remake_hash() {

    int Q, op, val;

    f.open(input.c_str());
    g.open(output.c_str());

    f>>Q;
    while(Q--) {
        f>>op>>val;
        if(op == 1) {
            if(!(*this)[val])
                *this += val;
        }
        if(op == 2) {
            if((*this)[val])
                *this -= val;
        }
        if(op == 3)
            g<<(*this)[val]<<"\n";
    }

    f.close();
    g.close();

    return true;
}

/* ------------------------------------------------------------------------------------------- */

int main() {

    doublehash<int> myHash(300000, "hashuri.in", "hashuri.out");

    srand(time(0));

    bool ok = false;
    while(!ok)
        ok = myHash.remake_hash();

    return 0;
}