Pagini recente » Cod sursa (job #2570514) | Cod sursa (job #1951768) | Cod sursa (job #2120331) | Cod sursa (job #1411221) | Cod sursa (job #936643)
Cod sursa(job #936643)
#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 hash_base {
public:
hash_base<T>();
virtual bool remake_hash() = 0;
virtual bool operator[](T) = 0;
virtual void operator+=(T) = 0;
virtual void operator-=(T) = 0;
};
template<class T>
hash_base<T>::hash_base() {
;
}
/* ------------------------------------------------------------------------------------------- */
template<class T>
class cockooHash: public hash_base<T> {
private:
ifstream f;
ofstream g;
string input, output;
hash_function func1, func2;
T *H1, *H2;
int maxsteps, size, prime;
bool *viz1, *viz2;
public:
cockooHash<T>(int, string, string);
bool remake_hash();
bool operator[](T);
void operator+=(T);
void operator-=(T);
};
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>
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>::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: public hash_base<T> {
private:
ifstream f;
ofstream g;
string input, output;
hash_function func1, func2;
int size, prime;
vector<T> *H1, *H2;
public:
doublehash<T>(int, string, string);
bool remake_hash();
bool operator[](T);
void operator+=(T);
void operator-=(T);
};
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;
}
template<class T>
doublehash<T>::doublehash(int dim, string infile, string outfile) : hash_base<T>() {
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=H2[poz2].begin(); it!=H2[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=H2[poz2].begin(); it!=H2[poz2].end(); ++it)
if(*it == val) {
H2[poz2].erase(it);
return;
}
}
/* ------------------------------------------------------------------------------------------- */
int main() {
hash_base<int> *myHash;
srand(time(0));
myHash = new doublehash<int>(150000, "hashuri.in", "hashuri.out");
bool ok = false;
while(!ok)
ok = myHash->remake_hash();
return 0;
}