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


    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] = '';
                }
            }
            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
    ");
            else printf("NO
    ");
        }
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        while (scanf("%d%d", &n, &m) != EOF)
        {
            initTree();
            input();
            work();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    leetCode算法题(一)
    node学习笔记1(http模块)
    mySql常用命令总结
    django学习遇到的问题解决方式
    WebSSH2 界面ssh(转载)
    垃圾回收策略学习总结
    5种数组扁平化方法
    冒泡、插入、选择、归并、快速排序
    手写ES6数组方法
    HTTP options预请求
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/5371535.html
Copyright © 2020-2023  润新知