题意:给定个规则,个ip,问这些ip是否能和某个规则匹配,如果有多个规则,则匹配第一个。如果没能匹配成功,则认为是”allow”,否则根据规则决定是”allow”或者”deny”.


思路:字典树,将所有ip全部转换为01串,在字典树上面插入查找。

在求二进制时,注意补前缀0。

坑点:

1.字典树上每一个规则都应该带一个序号,表示这是第几个规则,因为题目要求第一个匹配,那么当你利用ip去寻找匹配的规则时,应该是找到序号最小的。

2.出现deny 0.0.0.0/0,说明所有无法匹配ip的都是deny,因为这些ip和这条规则匹配。

给大家贴几个测试数据:

5 2

deny 0.0.0.0/0

allow 0.0.0.0/0

deny 0.0.0.0/1

deny 0.0.0.0/2

allow 123.234.12.23/3

123.234.12.23

0.234.12.23

答案: NO NO

2 1

deny 1.1.1.1

allow 127.0.0.1

1.1.1.222

答案:YES

AC代码

#include <cstdio>
#include <cmath>
#include <cctype>
#include <bitset>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 1e5 + 5;
bool is_zero, tag;
struct node{
    int ok, order;
    node *nex[2];
    node() {
        ok = -1; //从未访问过
        nex[0] = nex[1] = NULL;
    }
}*root;
void init() {
    root = new node();
}

void insert(string &s, int n, int ok, int order) {
    node *p = root, *q;
    for(int i = 0; i < n; ++i) {
        int u = s[i] - '0';
        if(p->nex[u] == NULL) {
            q = new node();
            p->nex[u] = q;
        }
        p = p->nex[u];
        if(i == n-1 && p->ok == -1) {
            p->ok = ok;
            p->order = order;
        }
    }
}

bool search(string &s) {
    node *p = root;
    bool ok = true;
    int order = inf;
    for(int i = 0; i < s.size(); ++i) {
        int u = s[i]-'0';
        if(p->nex[u] == NULL) break;
        else {
            if(p->nex[u]->ok != -1 && p->nex[u]->order < order) {
                order = p->nex[u]->order;
                ok = p->nex[u]->ok;
            }
        }
        p = p->nex[u];
    }
    //printf("%d\n", order);
    if(is_zero && order == inf) return tag;
    return ok;
}

string get_binary(int x) {
    stack<int>sta;
    do{
        sta.push(x%2);
        x /= 2;
    }while(x);
    string ans = "";
    //补前缀0
    for(int i = 0; i < 8 - sta.size(); ++i) {
        ans += '0';
    }
    //得到二进制
    while(!sta.empty()) {
        ans += sta.top() + '0';
        sta.pop();
    }
    return ans;
}

void deal(char *s, int ok, int order) {
    int len = strlen(s);
    int ind = -1;
    for(int i = 0; i < len; ++i) {
        if(s[i] == '/') {
            ind = i;
            break;
        }
    }
    string ip = "";
    if(ind == -1) ind = len;
    for(int i = 0; i < ind;) {
        if(s[i] >= '0' && s[i] <= '9') {
            int num = 0;
            while(i < ind && s[i] >= '0' && s[i] <= '9'){
                num = num * 10 + (s[i] - '0');
                ++i;
            }
            ip += get_binary(num);
        }
        else ++i;
    }
    int n = 32;
    if(ind != -1 && ind != len) {
        int num = 0;
        for(int i = ind+1; i < len; ++i) {
            num = num * 10 + s[i] -'0';
        }
        if(num == 0 && !is_zero) {
            is_zero = 1;
            tag = ok;
        }
        n = num;
    }
    insert(ip, n, ok, order);
}
int main() {
    init();
    char kind[10], ip[40];
    int n, m;
    while(scanf("%d%d", &n, &m) == 2) {
        is_zero = 0;
        for(int i = 0; i < n; ++i) {
            scanf("%s %s", kind, ip);
            int ok = 0;
            if(kind[0] == 'a') ok = 1;
            deal(ip, ok, i);
        }
        for(int i = 0; i < m; ++i) {
            scanf("%s", ip);
            int x1, x2, x3, x4;
            sscanf(ip, "%d.%d.%d.%d", &x1, &x2, &x3, &x4);
            string res = get_binary(x1) + get_binary(x2) + get_binary(x3) + get_binary(x4);
            if(search(res)) printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
} 

如有不当之处欢迎指出!

hihoCoder 403 Forbidden 字典树的更多相关文章

  1. ACM学习历程—Hihocoder 1289 403 Forbidden(字典树 || (离线 && 排序 && 染色))

    http://hihocoder.com/problemset/problem/1289 这题是这次微软笔试的第二题,过的人比第三题少一点,这题一眼看过去就是字符串匹配问题,应该可以使用字典树解决.不 ...

  2. [Hihocoder 1289] 403 Forbidden (微软2016校园招聘4月在线笔试)

    传送门 #1289 : 403 Forbidden 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Little Hi runs a web server. Someti ...

  3. hihoCoder 1014trie树(字典树)

    hihoCoder 1014 题目提示已经很清楚了~ 贴代码…… #include <iostream> #include <cstdio> #include <cstr ...

  4. 微软2016校园招聘4月在线笔试 hihocoder 1289 403 Forbidden

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 Little Hi runs a web server. Sometimes he has to deny acces ...

  5. 逆序单词 HIhoCoder 1366 字典树

    逆序单词 HIhoCoder 1366 字典序 题意 在英文中有很多逆序的单词,比如dog和god,evil和live等等. 现在给出一份包含N个单词的单词表,其中每个单词只出现一次,请你找出其中有多 ...

  6. hihocoder #1289 : 403 Forbidden (2016 微软编程笔试第二题)

    #1289 : 403 Forbidden 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Little Hi runs a web server. Sometimes ...

  7. Trie树(字典树)

    传送门:http://hihocoder.com/problemset/problem/1014 #1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描 ...

  8. HihoCoder1656 : 前缀后缀查询([Offer收割]编程练习赛39)(字典树+小技巧)

    描述 给定一个包含N个单词的字典:{W1, W2, W3, ... WN},其中第i个单词Wi有具有一个权值Vi. 现在小Hi要进行M次查询,每次查询包含一个前缀字符串Pi和一个后缀字符串Si.他希望 ...

  9. 萌新笔记——用KMP算法与Trie字典树实现屏蔽敏感词(UTF-8编码)

    前几天写好了字典,又刚好重温了KMP算法,恰逢遇到朋友吐槽最近被和谐的词越来越多了,于是突发奇想,想要自己实现一下敏感词屏蔽. 基本敏感词的屏蔽说起来很简单,只要把字符串中的敏感词替换成"* ...

随机推荐

  1. JavaScript小结

    语法小结 /** * Created by M.C on 2017/5/26. */ /*弹框*/ //var message = "Hello world"; //alert(m ...

  2. libev学习笔记

    转 libev的使用--结合Socket编程 作者:cxy450019566 之前自己学过一些libev编程的基础,这次写压测刚好用上了,才算真正动手写了些东西,在这里做一些总结.写这篇文章是为了用浅 ...

  3. CentOS7搭建时间服务器-chrony(不坑)

    标签(linux): chrony 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 之前centos6我们一直用的ntp时间服务器,虽然到CentOS7上也可以装 ...

  4. java.lang.String中[ "张飞"+1+1 ] 和 [ "张飞"+(1+1) ]

    废话不多说,上代码: package com.core; public class StringTest { public static void main(String[] args) { Stri ...

  5. 强大的API测试工具Hitchhiker v0.9 基于UI的断言测试,回顾2017

    v0.9是Hitchhiker在2017农历年的最后一个版本,而起点正是刚过完2016农历年,农历2018即将到来,一年轮回,今天写点东西稍微回顾下hitchhiker的2017. 先还是说v0.9, ...

  6. Spring Boot快速入门(最新)

    本章通过完成Spring Boot基础项目的构建并实现一个简单的Http请求处理,让大家对Spring Boot有一个初步的了解,并体验其结构简单.开发快速的特性.预计阅读及演练过程将花费约5分钟. ...

  7. WEB消息推送-原理篇

    这篇文章主要讲述B/S架构中服务器“推送”消息给浏览器.内容涉及ajax论询(polling),comet(streaming,long polling).后面会附上源代码. 最近在工作有这么一个需求 ...

  8. ansible playbook实践(二)-基础相关命令

    ansible相关的命令: ansible  用来执行ansible管理命令 ansible-doc 用来获取模块的帮助文档 ansible-playbook 当有众多任务时,可编写成playbook ...

  9. Go笔记-垃圾回收集和SetFinalizer

    [垃圾回收]     1- Go的开发者也不用写代码来释放程序中不再使用的变量和结构占用内存,Go中有独立的进程,垃圾回收器(GC),处理这些事情.它会搜索不再使用的变量然后释放它们.     2- ...

  10. appium+python环境搭建

    一.环境 1.安装python. 2.安装appium. 3.安装pip 4.安装selenium 5.安装Appium-Python-Client       #cmd->cd setupto ...