恶意IP
waterOJ上的题,不得不说TA真是给力,条件限制得有点苛刻啊,只能用哈希表来做了。
首先熟悉下BKDRHash函数:
1 unsigned int BKDRHash(char *str) { 2 unsigned int seed = 131; 3 unsigned int hash = 0; 4 5 while (*str) { 6 hash = hash * seed + (*str++); 7 } 8 9 return (hash & 0x7FFFFFFF); 10 }
-
0x7FFFFFFF
是 0111 1111 1111 1111 1111 1111 1111 1111,相当于去掉了最高的符号位,将可能的负数转为正数。 - 关于字符串哈希的文章推荐:https://www.byvoid.com/blog/string-hash-compare 一个清华大牛的个人网站。
下面就是初始化hashTable的问题:
1 struct Node { 2 char *value; 3 Node *next; 4 5 Node(char *value_) { 6 value = value_; 7 next = NULL; 8 } 9 }; 10 11 Node **hashTable = new Node *[1000000]; 12 13 void initializeHash(int size) { 14 unsigned int hashCode; 15 char *temp = NULL; 16 17 for (int i = 0; i < size; i++) { 18 temp = new char[17]; 19 scanf("%s", temp); 20 21 hashCode = BKDRHash(temp) % 1000000; 22 if (hashTable[hashCode] == NULL) { 23 hashTable[hashCode] = new Node(temp); 24 } else { 25 Node *root = hashTable[hashCode]; 26 while (root->next != NULL) { 27 root = root->next; 28 } 29 30 root->next = new Node(temp); 31 } 32 } 33 }
- 临时字符串变量记得分配空间,scanf不能针对未被分配空间的指针操作
- 过程中通过画图是个不错的理解方式
- 我选择通过拉链法解决冲突问题,每个链表的头没有value
下一步就是开始查找判断:
1 void judgeIp(char *str) { 2 unsigned int hashCode = BKDRHash(str) % 1000000; 3 4 if (hashTable[hashCode] == NULL) { 5 printf("PASS\n"); 6 } else { 7 bool flag = true; 8 Node *root = hashTable[hashCode]; 9 while (root != NULL) { 10 if (strcmp(root->value,str) == 0) { 11 flag = false; 12 printf("FILTER\n"); 13 break; 14 } 15 root = root->next; 16 } 17 18 if (flag) { 19 printf("PASS\n"); 20 } 21 } 22 }
测试函数:
1 int main() 2 { 3 int size; 4 5 scanf("%d", &size); 6 7 for (int i = 0; i < 1000000; i++) { 8 hashTable[i] = NULL; 9 } 10 initializeHash(size); 11 12 scanf("%d", &size); 13 char str[17]; 14 for (int i = 0; i < size; i++) { 15 scanf("%s", str); 16 judgeIp(str); 17 } 18 19 return 0; 20 }