1000: 恶意IP 课程作业


1000: 恶意IP

Time Limit: 1 Sec  Memory Limit: 16 MB

Description

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\n");
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\n");
67                     break;
68                 }    
69                 root = root->next;
70             }
71             if (flag)
72                printf("PASS\n");
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 }
 
posted @ 2013-11-26 17:01  厕所门口~~  阅读(618)  评论(0编辑  收藏  举报