您的位置:首页 > 其它

微软2017实习生在线笔试题——hihocoder 1289——403 Forbidden

2016-04-10 16:10 399 查看
题目:http://hihocoder.com/problemset/problem/1289

分析:有N条已知的前缀字符串,回答M个query,每个query找到这N个字符串中第一个匹配的项,自然的想到O(length)复杂度的字典树Trie。

由于

(1)1 <= N, M <= 10^5

(2)字符串仅由01组成 >>> Trie的每个node仅含有2个子节点

(3)每个字符串最多包含32个字符 >>> 一个字符串最多需要32个节点来表示

所以,不超过32N(< 3.2*10^6)个节点就可以表示这N条字符串,并且查询不超过32M(< 3.2*10^6)个节点就能完成全部M个query

需要注意的是,和普通的“字符串是否在Trie上”查询不同,题目中的查询要求找到第一个匹配的前缀,所以我们必须在经过每个节点时“看看这个节点的序号是不是更小”

下面是AC代码,对“最多32位的、仅包含01的”字符串,这里用了一个int变量进行表示



#include <bits/stdc++.h>
using namespace std;

const int MAX_N = 100005 * 32;
const int kUndefine = 0;
const int kDeny     = 1;
const int kAllow    = 2;

struct Node
{
Node* ch[2];
int   state;            // whether to allow the ip(formed by edges from root to this node)
int   order;            // the rule's index
};
Node nodes[MAX_N] = {0};    // initialize all node states to kUndefine
int  idx = 0;               // index of the next available node

void insert(Node* p, int ip, int len, int state, int order)
{
unsigned b = 1 << 31; // as we want an unsigned right shift
for(; len--; b >>= 1){
int i = b & ip ? 1 : 0;
if(p->ch[i] == 0){
// new a child node
p->ch[i] = nodes + idx++;
}
p = p->ch[i];
}
// we can not override former rules with latter ones
if(p->state == kUndefine || p->order > order){
p->state = state;
p->order = order;
}
}

int check(Node* p, int ip)
{
int state = kUndefine, order;
unsigned b = 1 << 31;
for(; b; b >>= 1){
int i = b & ip ? 1 : 0;
if(p->ch[i] == 0) break; // stop matching here
p = p->ch[i];
if(p->state != kUndefine){
// so p is an ending node here
if(state == kUndefine || order > p->order){
state = p->state;
order = p->order;
}
}
}
return state;
}

int main()
{
int i, n, m, a, b, c, d, ip, len, state, global = kUndefine;
char s[8];
scanf("%d%d", &n, &m);

// build trie
Node* root = nodes + idx++;
for(i = 0; i < n && global == kUndefine; ++i){
// input: rule ip[/len]
scanf("%s %d.%d.%d.%d", s, &a, &b, &c, &d);
ip = (a << 24) | (b << 16) | (c << 8) | d;
if(getchar() == '/') scanf("%d", &len);
else len = 32;
// insert trie
state = s[0] == 'a' ? kAllow : kDeny;
if(len == 0){
// the very last rule that counts (matching everything)
global = state;
}
else insert(root, ip, len, state, i);
}
// eat all rules after the matching-everything rule
for(; i < n; ++i){
scanf("%s %d.%d.%d.%d", s, &a, &b, &c, &d);
if(getchar() == '/') scanf("%d", &len);
}

// do query
for(i = 0; i < m; ++i){
scanf("%d.%d.%d.%d", &a, &b, &c, &d);
ip = (a << 24) | (b << 16) | (c << 8) | d;
state = check(root, ip);
if(state == kUndefine){
// no matched prefix, use global rule
state = global;
}
puts(state == kDeny ? "NO" : "YES");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: