|

题意:问有多少个单词有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;
}
|