1000: 恶意IP
Time Limit: 1 Sec Memory Limit: 16 MBDescription
Water同学最近好不容易学会了用Tornado建起一个个人的Website,并且成功上线了。
来访用户逐渐增多,但Water发现总有些恶意用户很喜欢刷屏,总是回复些评论如“楼主不要放弃治疗!”,“楼主药不能停!”之类的。Water感受到了这个世界满满的恶意,他很不爽,决定将这部分恶意用户过滤掉。
他已经掌握到这些用户的IP了,但是过滤IP这件事情对于数据结构挂了的他来说实在是有些困难,所以他来找你帮忙了!
IP格式为 a.b.c.d , 其中 a,b,c,d均为[0,255]之间的整数。
Input
只有一组数据。第一行为一个整数N [0, 1 000 000],代表恶意IP列表的长度。接下来N行是N个恶意IP。
然后紧随一个整数M [0, 1 000 000],代表访问IP的长度。接下来M行是M个来访IP。
你需要判断该来访IP是否在恶意IP列表中。
Output
如果来访IP是恶意IP,则输出 FILTER,否则输出 PASS。
Sample Input
5
233.233.233.233
250.250.250.250
10.20.30.40
123.255.123.255
172.18.182.69
6
10.123.128.245
233.233.233.233
172.18.182.253
102.30.40.50
172.18.182.96
172.18.182.69
Sample Output
PASS
FILTER
PASS
PASS
PASS
FILTER
这是我们数据结构的一道题,这道题本来不难,只要时间内存足够一个map就可以了,关键是时间要求1s内存是16MB,并且坑的是,测试数据量1 000 000组。那么这就要讲究策略了。首先不能用c++的STL和输入输出流还有string吧。。这些都是很耗空间和时间的。要效率就得选择C语言了。
然后是搜索问题,我们要根据字符串来搜索。在这里不管是快排还是归并都是达不到要求的,因为数据量太大。那么要选择什么呢?肯定哈希啦。。
所以下面就是怎么构造哈希表的问题了。因为键值是字符串不能当数组的下标,而且建数组的话也要注意大小问题。我选择的是BKDRHash函数,因为这个函数还是比较常用的。函数如下:
1 unsigned int BKDRHash(char *str) 2 { 3 unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. 4 unsigned int hash = 0; 5 6 while (*str) 7 { 8 hash = hash * seed + (*str++); 9 } 10 11 return (hash & 0x7FFFFFFF); 12 }
这里因为数据量最大是 1 000 000, 那么我们就构建一个 1 000 000 大小的数组吧。然后因为当字符串长的时候 BKDRHash()函数的返回值其实是很大的,所以返回值要对 1 000 000取余。
还有一个要注意的问题是冲突问题,一般情况下我一般用拉链法。。所以就拉链了。。。
下面是我的代码实现,因为写得比较急有点挫。。。
1 #include <iostream> 2 #include <stdio.h> 4 #include <string.h> 5 6 using namespace std; 7 8 unsigned int BKDRHash(char *str) { 9 unsigned int seed = 131; 10 unsigned int hash = 0; 11 12 while (*str) { 13 hash = hash * seed + (*str++); 14 } 15 16 return (hash & 0x7FFFFFFF); 17 } 18 19 struct Node { 20 char* value; 21 Node* next; 22 //value is link to a list which has conflict elements 23 Node(char* value_ = NULL){ 24 value = value_; 25 next = NULL; 26 } 27 }; 28 29 Node **arr = new Node*[1000001]; 30 31 void initializeHash(int N) { 32 //we can't only use a char[] here because the 33 //address of str will not change in this way, 34 //and the elements will be the same because 35 //they are just the same element 36 char* str; 37 for (int i = 0; i != N; i++) { 38 str = new char[17]; 39 scanf("%s", str); 40 unsigned int temp = BKDRHash(str); 41 temp %= 1000000; 42 43 if (arr[temp] == NULL) { 44 arr[temp] = new Node(str); 45 } else { 46 Node* root = arr[temp]; 47 while (root->next != NULL) { 48 root = root->next; 49 } 50 root->next = new Node(str); 51 } 52 } 53 } 54 55 void judgeIp(char* str) { 56 unsigned int temp = BKDRHash(str); 57 temp %= 1000000; 58 if (arr[temp] == NULL) { 59 printf("PASS "); 60 } else { 61 bool flag = true; 62 Node* root = arr[temp]; 63 while (root != NULL) { 64 if (strcmp((root->value), str) == 0) { 65 flag = false; 66 printf("FILTER "); 67 break; 68 } 69 root = root->next; 70 } 71 if (flag) 72 printf("PASS "); 73 } 74 } 75 int main(int argc, char const *argv[]) 76 { 77 int N; 78 scanf("%d", &N); 79 for (int i = 0; i != 1000001; i++) 80 arr[i] = NULL; 81 initializeHash(N); 82 83 char str[17]; 84 scanf("%d", &N); 85 for (int i = 0; i != N; i++) { 86 scanf("%s", str); 87 judgeIp(str); 88 } 89 return 0; 90 }