http://hihocoder.com/problemset/problem/1289
这题是这次微软笔试的第二题,过的人比第三题少一点,这题一眼看过去就是字符串匹配问题,应该可以使用字典树解决。不过当时还有一个想法就是离线处理,把所有查询进行排序,然后用rule去匹配查询,进行染色处理,而且每个查询只进行一次染色。事实证明,如果比赛的时候采用第二种方法应该能拿全分,但是我用了第一种方法,导致只拿了10分。。。因为我没有考虑同一个rule出现两次的情况,但是字典树中会直接被后面的rule覆盖,所以需要判定更新最小的index,但是离线染色的情况只染一次,所以第二种会直接跳过这种坑点。。
字典树比较好考虑,就是直接存入rule的first mask部分,然后添加一个index和isok标记表示是第几个rule和rule的类型,然后后面的ip一旦匹配的话,只匹配index最小的。然后一些边界及不存在情况进行特判一下。
当时写完字典树WA只拿了10分,然后字典树也没有发现哪里写的有问题,就一直纠结与是不是数据溢出之类的。。唉,也只能说明水平还没到把,也不知道能不能进面试。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <map> #include <queue> #include <vector> #include <string> #define LL long long using namespace std; const int maxN = 100005; const int maxLen = 32;//len表示数的二进制最大长度 struct Trie { int index; int next[2]; }tree[maxN*maxLen]; bool isok[maxN*maxLen]; int cnt; void initTree() { cnt = 0; memset(tree, -1, sizeof(tree)); } void add(int x, bool flag, int index, int len) { int now = 0; bool k; for (int i = len-1; i >= 0; i--) { k = x&(1<<i); if (tree[now].next[k] == -1) tree[now].next[k] = ++cnt; now = tree[now].next[k]; } if (tree[now].index == -1 || tree[now].index > index)//只因为这种情况,只拿了10分。。 { tree[now].index = index; isok[now] = flag; } } bool query(int x) { int v = -1, now = 0; bool k, flag; for (int i = maxLen-1; i >= 0; i--) { if (tree[now].index != -1) { if (v == -1 || v > tree[now].index) { v = tree[now].index; flag = isok[now]; } } k = x&(1<<i); if (tree[now].next[k] == -1) break; now = tree[now].next[k]; } if (tree[now].index != -1) { if (v == -1 || v > tree[now].index) { v = tree[now].index; flag = isok[now]; } } if (v == -1) return true; else return flag; } int n, m; char op[15]; char str[105]; void input() { bool flag; int k, a, b, c, d, r, len; for (int i = 0; i < n; ++i) { scanf("%s%s", op, str); if (op[0] == ‘a‘) flag = true; else flag = false; r = -1; len = strlen(str); for (int j = 0; j < len; ++j) { if (str[j] == ‘/‘) { sscanf(str+j+1, "%d", &r); str[j] = ‘\0‘; } } sscanf(str, "%d.%d.%d.%d", &a, &b, &c, &d); k = (a<<24)+(b<<16)+(c<<8)+d; if (r != -1) k >>= (32-r); else r = maxLen; add(k, flag, i, r); } } void work() { bool flag; int k, a, b, c, d; for (int i = 0; i < m; ++i) { scanf("%d.%d.%d.%d", &a, &b, &c, &d); k = (a<<24)+(b<<16)+(c<<8)+d; flag = query(k); if (flag) printf("YES\n"); else printf("NO\n"); } } int main() { //freopen("test.in", "r", stdin); while (scanf("%d%d", &n, &m) != EOF) { initTree(); input(); work(); } return 0; }
时间: 2024-10-12 00:51:56