uva 10391(Hash)

uva 10391(Hash)_第1张图片



题意:问有多少个单词有2个单词组成




题解:由于串很多,但是单词很短,那么我们直接分解单词就好啦,每个位置枚举可能,那么我们只要在词库里面找这2个单词就好啦,现在需要设计一个高效的算法快速找到单词

1:map 查找速度logN


2:hash表,将单词hash后在数组里面查找,如果足够离散那么平均的时间复杂度应该是能达到O(1)的查找速度,我使用的是SDBMHash函数,这个函数相当其他的hash函数离散的表现最好,冲突少,也可以直接使用STL的hash函数,不过要支持c++11才可以使用。这里给出2种解法


模板


unsigned int gethash(const string &st)//SDBMHash
{
	unsigned int Hash = 0;
	for (int i = 0; i < st.size(); i++)
	{
		Hash = (st[i]) + (Hash << 6) + (Hash << 16) - Hash;
	}
	return (Hash & 0x7FFFFFFF)%mod;
}

void insert(const string &st)
{
	int c = HASH(st)%mod;
	str[cnt] = st;
	Next[cnt] = head[c];
	head[c] = cnt++;
}

bool find(const string &st)
{
	int c = HASH(st)%mod;
	for (int i = head[c]; i != -1; i = Next[i])
	{
		if (str[i] == st)
			return true;
	}
	return false; 
}




手写hash表:


#include<cstdio>  
#include<cstring>  
#include<cstdlib>  
#include<cmath>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<set>  
#include<queue>  
#include<string>  
#include<bitset>  
#include<utility>  
#include<functional>  
#include<iomanip>  
#include<sstream>  
#include<ctime>  
using namespace std;

typedef long long LL;
enum { N = int(1e6+10) ,inf=int(0x3f3f3f3f),mod =int(1e6+3) };
string s,str[N];
int head[N], Next[N];
int cnt;


void init()
{
	cnt = 0;
	memset(head, -1, sizeof(head));
}

unsigned int gethash(const string &st)//SDBMHash
{
	unsigned int Hash = 0;
	for (int i = 0; i < st.size(); i++)
	{
		Hash = (st[i]) + (Hash << 6) + (Hash << 16) - Hash;
	}
	return (Hash & 0x7FFFFFFF)%mod;
}

void insert(const string &st)
{
	int c = gethash(st);
	str[cnt] = st;
	Next[cnt] = head[c];
	head[c] = cnt++;
}

bool find(const string &st)
{
	int c = gethash(st);
	for (int i = head[c]; i != -1; i = Next[i])
	{
		if (str[i] == st)
			return true;
	}
	return false; 
}

int main()
{
#ifdef CDZSC  
	freopen("i.txt", "r", stdin);
	//freopen("o.txt","w",stdout);  
	int _time_jc = clock();
#endif  
	ios::sync_with_stdio(false);
	string tmp1,tmp2;
	init();
	while (cin >> s)insert(s);
	for (int i = 0; i < cnt; i++)
	{
		for (int k = 1; k < str[i].size(); k++)
		{
			tmp1 = str[i].substr(0, k);
			tmp2 = str[i].substr(k, str[i].size() - k);
			if (find(tmp1) && find(tmp2))
			{
				cout << str[i] << endl;
				break;
			}
		}
	}
	return 0;
}



STL的Hash函数,需要c++11标准支持才能用


#include<cstdio>  
#include<cstring>  
#include<cstdlib>  
#include<cmath>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<set>  
#include<queue>  
#include<string>  
#include<bitset>  
#include<utility>  
#include<functional>  
#include<iomanip>  
#include<sstream>  
#include<ctime>  
using namespace std;

typedef long long LL;
enum { N = int(1e6+10) ,inf=int(0x3f3f3f3f),mod =int(1e6+3) };
string s,str[N];
int head[N], Next[N];
int cnt;



void init()
{
	cnt = 0;
	memset(head, -1, sizeof(head));
}

hash<string>HASH;
void insert(const string &st)
{
	int c = HASH(st)%mod;
	str[cnt] = st;
	Next[cnt] = head[c];
	head[c] = cnt++;
}

bool find(const string &st)
{
	int c = HASH(st)%mod;
	for (int i = head[c]; i != -1; i = Next[i])
	{
		if (str[i] == st)
			return true;
	}
	return false; 
}

int main()
{
#ifdef CDZSC  
	freopen("i.txt", "r", stdin);
	//freopen("o.txt","w",stdout);  
	int _time_jc = clock();
#endif  
	ios::sync_with_stdio(false);
	string tmp1,tmp2;
	init();
	while (cin >> s)insert(s);
	for (int i = 0; i < cnt; i++)
	{
		for (int k = 1; k < str[i].size(); k++)
		{
			tmp1 = str[i].substr(0, k);
			tmp2 = str[i].substr(k, str[i].size() - k);
			if (find(tmp1) && find(tmp2))
			{
				cout << str[i] << endl;
				break;
			}
		}
	}
	return 0;
}


你可能感兴趣的:(uva 10391(Hash))