Cod sursa(job #916468)

Utilizator cdascaluDascalu Cristian cdascalu Data 16 martie 2013 15:53:01
Problema Hashuri Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 5.63 kb
//Pentru detalii:
//http://stackoverflow.com/a/98179
//http://www.isthe.com/chongo/tech/comp/fnv/
//(numerele sunt siruri de caractere)
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <string.h>
#include <sstream>
using namespace std;

template <class Type>
class FNV_Hash
{
    public:

        FNV_Hash(unsigned int);
        ~FNV_Hash();

        unsigned int       hash_function(Type);
        void                insert_element(Type);
        void                remove_element(Type);
        bool                check_element(Type);
        string              convert_element(Type);
    private:

        unsigned int             hash_size;
        unsigned int             FNV_prime;
        unsigned int             FNV_init;

        vector<Type>               *hash_vector;
};

template <class Type>
class Solver
{
    public:

        Solver(char*, char*, int);
        ~Solver();

        void solve();

    private:

        ifstream            f;
        ofstream            g;
        FNV_Hash<Type>      *hash;
};

int main()
{
    Solver<int> *my_solver;
    my_solver = new Solver<int>("hashuri.in", "hashuri.out", 699967);

    my_solver->solve();

    delete my_solver;
    my_solver = 0;

    return 0;
}

//==========================================================================
//========================== FNV_Hash ======================================
//==========================================================================

template<class Type>
FNV_Hash< Type >::FNV_Hash(unsigned int size)
{
    hash_vector             = new vector<Type>[size];
    hash_size               = size;
    FNV_prime               = 16777619;
    FNV_init                = 2166136261U;
}

//==========================================================================

template<class Type>
FNV_Hash< Type >::~FNV_Hash()
{
    delete []hash_vector;
    hash_vector = 0;
}

//==========================================================================

template<>
string FNV_Hash< string >::convert_element(string elem)
{
    return elem;
}

//--------------------------------------------------------------------------

template<class Type>
string FNV_Hash< Type >::convert_element(Type elem)
{
    ostringstream   stream;
    stream<<elem;
    return stream.str();
}

//==========================================================================

template<class Type>
unsigned int FNV_Hash< Type >::hash_function(Type elem)
{
    string good_elem    = convert_element(elem);

    unsigned int return_value;
    char last_part;
    unsigned int i=0,size = good_elem.size();;

    for(return_value = FNV_init;i<size;++i)
    {
        last_part           = good_elem[i];
        return_value        = return_value ^ char(last_part);
        return_value        = return_value * FNV_prime;
    }
    return return_value;
}

//--------------------------------------------------------------------------

template<>
unsigned int FNV_Hash<int>::hash_function(int elem)
{
    int last_part;
    unsigned int return_value;

    for(return_value = FNV_init;elem;elem/=10)
    {
        last_part           = elem%10;
        return_value        = return_value ^ char(last_part + 'a');
        return_value        = return_value * FNV_prime;
    }
    return return_value;
}

//==========================================================================

template<class Type>
void FNV_Hash<Type>::insert_element(Type elem)
{
    unsigned int hash_key       = hash_function(elem) % hash_size;

    for(typename vector<Type>::iterator it = hash_vector[hash_key].begin();it!=hash_vector[hash_key].end();++it)
    {
        if(*it == elem)
            return;
    }
    hash_vector[hash_key].push_back(elem);
}

//==========================================================================

template<class Type>
void FNV_Hash<Type>::remove_element(Type elem)
{
    unsigned int hash_key       = hash_function(elem) % hash_size;

    for(typename vector<Type>::iterator it = hash_vector[hash_key].begin();it!=hash_vector[hash_key].end();++it)
    {
        if(*it == elem)
        {
            hash_vector[hash_key].erase(it);
            return;
        }
    }
}

//==========================================================================

template<class Type>
bool FNV_Hash<Type>::check_element(Type elem)
{
    unsigned int hash_key       = hash_function(elem) % hash_size;

    for(typename vector<Type>::iterator it = hash_vector[hash_key].begin();it!=hash_vector[hash_key].end();++it)
    {
        if(*it == elem)
        {
            return true;
        }
    }
    return false;
}

//==========================================================================
//========================== Solver ========================================
//==========================================================================

template <class Type>
Solver<Type>::Solver(char* input_file, char* output_file, int hash_size)
{
    f.open(input_file);
    g.open(output_file);
    hash     = new FNV_Hash<Type>(hash_size);
}

//==========================================================================

template <class Type>
Solver<Type>::~Solver()
{
    delete hash;
    hash = 0;

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

//==========================================================================

template <class Type>
void Solver<Type>::solve()
{
    int N,op;

    Type val;

    f>>N;
    while(N--)
    {
        f>>op>>val;
        if(op == 3)
        {
            if(hash->check_element(val))
                g<<"1\n";
            else g<<"0\n";
        }
        else if(op == 2)
        {
            hash->remove_element(val);
        }
        else if(op == 1)
        {
            hash->insert_element(val);
        }
    }
}