Cod sursa(job #937365)

Utilizator UnforgivenMihai Catalin Botezatu Unforgiven Data 10 aprilie 2013 09:21:22
Problema Hashuri Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 7.89 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <time.h>
#include <cstdlib>
#include <string>
#include <typeinfo>


using namespace std;

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

// Clasa de Baza ->

class Hash_Base
{

    public:

    Hash_Base(int size)
    {
        table1 = new int[size];
        table2 = new int[size];
        prim = 1000000009;
        operations = new vector < pair<int,bool> >;

        fill(table1 , table1 + size , 0);
        fill(table2 , table2 + size , 0);
        srand(time(NULL));
        hash_size = size;
        generate_random();
    }

    void generate_random();

    virtual int hash_function1(int&) = 0;
    virtual int hash_function2(int&) = 0;

    virtual bool insert (int&) = 0;
    virtual bool erase (int&) = 0;
    virtual bool find (int&) = 0;

    void operator *= (int&);
    void operator /= (int&);
    bool operator %= (int&);

    Hash_Base& operator * (int&);
    Hash_Base& operator / (int&);
    Hash_Base& operator % (int&);


    int a1,b1,a2,b2,prim;
    int * table1;
    int * table2;
    int hash_size;

    vector < pair <int,bool> > *operations;

};

void Hash_Base::operator/= (int &value)
{
    int locatie_noua = value;
    operations -> push_back(make_pair(locatie_noua,false));
    erase(locatie_noua);
}

bool Hash_Base::operator%= (int & value)
{
    int adress = value;
    return find(adress);
}

void Hash_Base::operator*=(int & value)
{
    int locatie_noua = value;
    operations -> push_back(make_pair(locatie_noua,true));

    if (insert(locatie_noua) == false)
    {
        generate_random();
        fill(table1 , table1 + hash_size , 0);
        fill(table2 , table2 + hash_size , 0);
        bool ok = false;
        while (ok == false)
        {
            ok = true;
            for (int i =0;i<operations -> size();i++)
            {
                bool op = (*operations)[i].second;
                int adress_data = (*operations)[i].first;
                if (op)
                {
                    if (!insert(adress_data))
                    {
                        ok = false;
                        break;
                    }
                }
                else
                {
                    erase(adress_data);
                }
            }
        }
    }
}

Hash_Base&  Hash_Base::operator* (int& value)
{
    *this *= value;
    return *this;
}


Hash_Base&  Hash_Base::operator/ (int& value)
{
    *this /= value;
    return *this;
}


Hash_Base&  Hash_Base::operator% (int& value)
{
    cout << (*this %= value);
    return *this;
}

void Hash_Base::generate_random()
{
    a1 = rand() % hash_size;
    a2 = rand() % hash_size;
    b1 = rand() % hash_size;
    b2 = rand() % hash_size;
}

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

// Cuckoo Hash pentru Int32 ->

class Hash_Integer : public Hash_Base
{

    int hash_function1(int&);
    int hash_function2(int&);

    public:

    Hash_Integer(int size) : Hash_Base(size)
    {
    }

    bool insert(int&);
    bool erase(int&);
    bool find(int&);
};

int Hash_Integer::hash_function1(int & value)
{
    return (((long long)a1 + (long long)value * (long long)b1 ) % (long long)prim) % (long long)hash_size;
}

int Hash_Integer::hash_function2(int & value)
{
    return (((long long)a2 + (long long)value * (long long)b2 ) % (long long)prim) % (long long)hash_size;
}

bool Hash_Integer::erase(int & value)
{
    int h1 = hash_function1(*(int*)value);
    int h2 = hash_function2(*(int*)value);

    if (table1[h1] != 0 &&*(int*)table1[h1] == *(int*)value)
    {
        int * adress = (int*)table1[h1];
        delete adress;

        table1[h1] = 0;
        return true;
    }

    if (table2[h2] !=0 && *(int*)table2[h2] == *(int*)value)
    {

        int * adress = (int*)table2[h2];
        delete adress;

        table2[h2] = 0;
        return true;
    }

    return false;
}

bool Hash_Integer::find(int & value)
{

    int h1 = hash_function1(*(int*)value);
    int h2 = hash_function2(*(int*)value);

    if (table1[h1] != 0 &&*(int*)table1[h1] == *(int*)value)
    {
        return true;
    }

    if (table2[h2] != 0 && *(int*)table2[h2] == *(int*)value)
    {
        return true;
    }

    return false;

}

bool Hash_Integer::insert(int & value)
{
    if (find(value)) return true;
    char which = 1;

    for (int i =0;i<30;i++)
    {
        int h1 = hash_function1(*(int*)value);
        int h2 = hash_function2(*(int*)value);
        if (table1[h1] == 0)
        {
            table1[h1] = value;
            return true;
        }
        else if(table2[h2] == 0)
        {
            table2[h2] = value;
            return true;
        }
        else
        {
            if (which == 1)
            {
                swap(value,table1[h1]);
            }
            else
            {
                swap(value,table2[h2]);
            }
            which = - which;
        }
    }
    return false;
}

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

// Cuckoo hash pentru Stringuri ->

class Hash_String : public Hash_Base
{

    int hash_function1(int&);
    int hash_function2(int&);

    public:

    Hash_String(int size) : Hash_Base(size)
    {
    }

    bool insert(int&);
    bool erase(int&);
    bool find(int&);
};

int Hash_String::hash_function1(int & value)
{
    int key = 0;
    string cpy = *(string*)value;

    for (int i =0;i<cpy.size();i++)
    {
        key += ((int)cpy[i] * b1 + a1) % hash_size;
        key %= hash_size;
    }
    return key;
}

int Hash_String::hash_function2(int & value)
{
    int key = 0;
     string cpy = *(string*)value;

    for (int i =0;i<cpy.size();i++)
    {
        key += ((int)cpy[i] * b2 + a2) % hash_size;
        key %= hash_size;
    }
    return key;
}

bool Hash_String::erase(int & value)
{
    int h1 = hash_function1(value);
    int h2 = hash_function2(value);

    if (table1[h1] != 0 &&*(string*)table1[h1] == *(string*)value)
    {
        string * adress = (string*)table1[h1];
        delete adress;

        table1[h1] = 0;
        return true;
    }

    if (table2[h2] !=0 && *(string*)table2[h2] == *(string*)value)
    {

        string * adress = (string*)table2[h2];
        delete adress;

        table2[h2] = 0;
        return true;
    }

    return false;
}

bool Hash_String::find(int & value)
{

    int h1 = hash_function1(value);
    int h2 = hash_function2(value);

    if (table1[h1] != 0 &&*(string*)table1[h1] == *(string*)value)
    {
        return true;
    }

    if (table2[h2] != 0 && *(string*)table2[h2] == *(string*)value)
    {
        return true;
    }

    return false;

}

bool Hash_String::insert(int & value)
{
    if (find(value)) return true;
    char which = 1;

    for (int i =0;i<30;i++)
    {
        int h1 = hash_function1(value);
        int h2 = hash_function2(value);
        if (table1[h1] == 0)
        {
            table1[h1] = value;
            return true;
        }
        else if(table2[h2] == 0)
        {
            table2[h2] = value;
            return true;
        }
        else
        {
            if (which == 1)
            {
                swap(value,table1[h1]);
            }
            else
            {
                swap(value,table2[h2]);
            }
            which = - which;
        }
    }
    return false;
}

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

int main()
{
    Hash_Base *t = new Hash_Integer(900001);
    ifstream input("hashuri.in");
    ofstream output("hashuri.out");
    int n;
    input >> n;
    for (int i =0;i<n;i++)
    {
        int op;
        int x;
        input >> op >> x;

        int *new_instance = new int(x);
        int adress = (int)new_instance;

        if (op == 1)
        {
            *t *= adress;
        }
        if (op == 2)
        {
            *t /= adress;
        }
        if (op == 3)
        {
            output << (*t %= adress) << "\n";
        }
    }
    /*
    int x = 3;
    *t * x % x / x % x / x / x % x * x / x * x % x;
    */

    return 0;
}