在一本通上面看到的这道题,但是书上把它划进了hash表的练习里面(数据范围稍小一点,为:1<=N<=10000,1<=M<=500000) ,然而我尝试模仿书上的思路与深基中有关hash表部分的代码的时候只能AC5个点;并且空间占用很大,质数稍微取大一点就会MLE。
题解中的答案要么使用的是trie树,要么使用的是双哈希,还有暴力二分搜索的。
代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef unsigned long long ull;
const int p = 999983;//取模质数
vector<string>s[p + 2];//创建数组
bool used[p] = {0};//判断名字是否被点过
inline ull hash2(char a[])
{//求hash值
ull res = 0; int len = strlen(a);
for (int i = 0; i < len; i++)
{
res += 26 * res + (ull)a[i];
}
return res % p;
}
int main()
{
int n, m; scanf("%d", &n);
for (int i = 0; i < n; i++)
{
char a[52]; scanf("%s", a);
string gjr = a;
ull hashi = hash2(a);
s[hashi].push_back(gjr);//读入数组元素
}
scanf("%d", &m);
for (int i = 0; i < m; i++)
{
char a[52]; scanf("%s", a);
string gjr = a;
ull hashi = hash2(a);
bool symbol = 0;//对应hash值是否在数组中
for (int u = 0; u < s[hashi].size(); u++)
{//遍历hash值
if (used[hashi])
{//点过了就repet
printf("REPEAT\n"); symbol = 1;
break;
}
else
{//没点过就ok 然后更改点名状态
used[hashi] = 1;
printf("OK\n"); symbol = 1;
break;
}
}
if (!symbol)//如果不在那就是点错了名
{
printf("WRONG\n");
}
}
return 0;
}