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

题目: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 
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;
}


你可能感兴趣的:(Interview相关,hihocoder,Trie)