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] = ‘\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

ACM学习历程—Hihocoder 1289 403 Forbidden(字典树 || (离线 && 排序 && 染色))的相关文章

ACM学习历程—HDU 4287 Intelligent IME(字典树 || map)

Description We all use cell phone today. And we must be familiar with the intelligent English input method on the cell phone. To be specific, the number buttons may correspond to some English letters respectively, as shown below: 2 : a, b, c    3 : d

ACM学习历程—HDU2222 Keywords Search(字典树)

Keywords Search Description In the modern time, Search engine came into the life of everybody like Google, Baidu, etc.       Wiskey also wants to bring this feature to his image retrieval system.       Every image have a long description, when users

ACM学习历程——hihoCoder挑战赛10A 01串(策略)

时间限制:7000ms 单点时限:1000ms 内存限制:256MB 描述 给定两个整数n和m,求是否存在恰好包含n个0和m个1的01串S,使得S中不存在子串"001"和"11". 如果存在符合条件的01串则输出字典序最小的S,否则输出NO. 输入 一行两个整数,表示n和m.(0<=n,m<=100000,0<n+m) 输出 一行一个字符串,为字典序最小的S或者NO. 样例输入 2 3 样例输出 10101 由于不能存在001和11,故只能1010

ACM学习历程—Hihocoder 1233 Boxes(bfs)(2015北京网赛)

hihoCoder挑战赛12 时间限制:1000ms 单点时限:1000ms 内存限制:256MB   描述 There is a strange storehouse in PKU. In this storehouse there are n slots for boxes, forming a line. In each slot you can pile up any amount of boxes. The limitation is that you can only pile a

ACM学习历程—Hihocoder 1164 随机斐波那契(数学递推)

时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 大家对斐波那契数列想必都很熟悉: a0 = 1, a1 = 1, ai = ai-1 + ai-2,(i > 1). 现在考虑如下生成的斐波那契数列: a0 = 1, ai = aj + ak, i > 0, j, k从[0, i-1]的整数中随机选出(j和k独立). 现在给定n,要求求出E(an),即各种可能的a数列中an的期望值. 输入 一行一个整数n,表示第n项.(1<=n<=500) 输出 一行一个

ACM学习历程—Hihocoder 1291 Building in Sandbox(dfs &amp;&amp; 离线 &amp;&amp; 并查集)

http://hihocoder.com/problemset/problem/1291 前几天比较忙,这次来补一下微软笔试的最后一题,这题是这次微软笔试的第四题,过的人比较少,我当时在调试B题,没时间看这一题.不过打过之前一场BestCoder的应该都会有点思路,虽然BC那题是二维,这题是三维的,但是思路应该是一样的,没错,就是离线加并查集. 正过来考虑的时候,发现第一个要求相邻块是好处理的,但是第二个要求能否到达(1000, 1000, 1000)这个条件似乎比较难判断,当时BC上的题根据题

ACM学习历程—Hihocoder 1288 Font Size(暴力 || 二分)

http://hihocoder.com/problemset/problem/1288 这题是这次微软笔试的第一题,关键的是s的上限是min(w, h),这样s的范围只有到1000,这样就可以直接暴力了,当然用二分也行,不过暴力写起来更快一点. 代码: #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #inc

ACM学习历程—Hihocoder 1290 Demo Day(动态规划)

http://hihocoder.com/problemset/problem/1290 这题是这次微软笔试的第三题,过的人比第一题少一点,这题一眼看过去就是动态规划,不过转移方程貌似不是很简单,调试了比较久才正确,不过好在是1A,但是最后只留了一个小时多一点给B题,也导致了B题最后也没能AC掉.首先状态是很好确定的p[i][j][k]表示走到第i行第j个格子时,方向是k的情况下的最小改变格子数目.(k from {0, 1})而且由于只有往下和往右走,所以中间过程进行转移时改变的格子不会影响后

ACM学习历程—Hihocoder 1139 二分&#183;二分答案(bfs)

http://hihocoder.com/problemset/problem/1139 这题提示上写的是二分,但是感觉不二分应该也可以,至少题目是AC的... 二分的思想就是二分答案的值,看能不能在k步内,得到这个答案值,可以采用bfs来判定. 不二分的话,就是需要一个dis[]数组来保存在前k步内,每个点的最小索敌值,因为bfs在往后的过程中step是越来越大的,所以前面能达到更小的,显然不会重复再跑大的,然后bfs的过程中更新即可.类似于spfa,但是没有对队列去重. 代码: #inclu