本题乍看像是线段树之类的区间操作,只是由于仅仅是须要查找ip的前缀,故此事实上是使用Trie来做。

挺高难度的Trie应用,做完这道题之后说明Trie功力有一定火候了。

这里的Trie使用到了Delete函数。这是个Trie函数中最难的函数了,当然要使用数组记录的方法水掉。也是能够的。这里不水。给出delete函数。

考点难点:

1 Trie的操作函数的灵活运用。主要难点是delete函数的灵活运用

2  在叶子节点全部的group id, 删除的时候要注意,不能一气删除了,有多个group id会挂在同一颗树中

3  源ip和目的ip或许在多个叶子节点中,要使用两个vector记录全部group id,然后使用查找两集合是否有公共值的算法解之

4 ip值转换为一个整数值记录就能够了,这里使用了unsigned,只是应该是int也能够的,由于仅仅须要操作其二进制值,和整数值无关。

5 使用mask值,mask值后面的0能够无论,加速程序

全部问题考虑全。高级数据结构中包含各种小问题处理,大算法中使用到多种小算法,综合难度超过5星级。做完后非常有成就感O(∩_∩)O哈哈~。

#include <stdio.h>
#include <bitset>
#include <vector>
#include <algorithm>
using namespace std; const int MAX_ID = 1024;
const int MAX_LINE = 32769;
const int MAX_N = 15;
const int ARR_SIZE = 2;
const int MAX_DIGIT = 32;
const int MAX_NODE = MAX_ID*MAX_DIGIT*MAX_N;
unsigned gEnableIdIpMask[MAX_ID][MAX_N<<1];
int gLen[MAX_ID], id; struct Node
{
int n;
vector<int> id;
Node *arr[ARR_SIZE];
}; void clearNode(Node *rt)
{
rt->n = 0;
rt->id.clear();
for (int i = 0; i < ARR_SIZE; i++)
{
rt->arr[i] = NULL;
}
} Node pool[MAX_NODE];
int poolID; void insertTrie(Node *trie, unsigned dig, unsigned mark, int id)
{
bitset<MAX_DIGIT> bi = dig;
int m = MAX_DIGIT - mark;
for (int i = MAX_DIGIT-1; i >= m; i--)
{
Node *&p = trie->arr[bi[i]];//注意*&p,操作同名地址变量
if (!p)//推断成if(p)。程序崩溃。
{
p = &pool[poolID++];
clearNode(p);
}
trie = p;
}
trie->n++;
trie->id.push_back(id);
} bool searchNode(Node *trie, unsigned dig, vector<int> &id)
{
bitset<MAX_DIGIT> bi = dig;
bool flag = false;
for (int i = MAX_DIGIT-1; i >= 0; i--)
{
trie = trie->arr[bi[i]];
if (!trie) return flag;
if (trie->n)
{
flag = true;
id.insert(id.end(), trie->id.begin(), trie->id.end());
}
}
return flag;
} inline bool isFreeNode(Node *rt)
{
for (int i = 0; i < ARR_SIZE; i++)
{
if (rt->arr[i]) return false;
}
return true;
} bool deleteNodeHelper(Node *trie, bitset<MAX_DIGIT> &bi, int mask, int id,
int lv = MAX_DIGIT-1)//注意lv含义。准确赋值
{
if (trie)
{
if (mask-1 == lv)//注意:下标计算。对齐
{
if (trie->n)
{
if (trie->n > 1)
{
int j = 0;
for (; j < trie->n; j++) if (trie->id[j] == id) break;
trie->id.erase(trie->id.begin()+j);
trie->n--;
}
else
{
trie->n = 0;
trie->id.clear();
return isFreeNode(trie);
}
}
}
else
{
if (deleteNodeHelper(trie->arr[bi[lv]], bi, mask, id, lv-1))
{
trie->arr[bi[lv]] = NULL;
return !trie->n && isFreeNode(trie);
}
}
}
return false;
} inline void deleteNode(Node *trie, unsigned dig, unsigned mask, int id)
{
bitset<MAX_DIGIT> bi = dig;
int m = MAX_DIGIT - mask; //注意长度计算
deleteNodeHelper(trie, bi, m, id);
} unsigned getIP()
{
unsigned ip = 0;
unsigned part;
for (int j = 3; j >= 0; j--)
{
scanf("%u", &part);
getchar();
ip |= part<<(j<<3);
}
return ip;
} int main()
{
char cmd;
unsigned ip, mask;
Node *trie = &pool[0];
clearNode(trie);
poolID = 1;
while (scanf("%c", &cmd) != EOF)
{
if (cmd == 'E')
{
scanf("%d", &id);
scanf("%d", gLen+id);
for (int i = 0; i < gLen[id]; i++)
{
ip = getIP();
scanf("%u", &mask);
gEnableIdIpMask[id][i<<1] = ip;
gEnableIdIpMask[id][i<<1|1] = mask;
insertTrie(trie, ip, mask, id);
}
getchar();
}
else if (cmd == 'D')
{
scanf("%d", &id);
getchar();
for (int i = 0; i < gLen[id]; i++)
{
deleteNode(trie, gEnableIdIpMask[id][i<<1],
gEnableIdIpMask[id][i<<1|1], id);
}
gLen[id] = 0;
}
else// if (cmd == 'F')
{
ip = getIP();
vector<int> ipSrc, ipDes;
bool src = searchNode(trie, ip, ipSrc);
ip = getIP();
if (src) src = searchNode(trie, ip, ipDes);
if (src)
{
sort(ipSrc.begin(), ipSrc.end());
sort(ipDes.begin(), ipDes.end());
bool hasSame = false;
for (int i = 0, j = 0;
i < (int)ipSrc.size() && j < (int)ipDes.size(); )
{
if (ipSrc[i] == ipDes[j])
{
hasSame = true;
break;
}
else if (ipSrc[i] < ipDes[j]) i++;
else j++;
}
if (hasSame) puts("F");
else puts("D");
}
else puts("D");
}
}
return 0;
}

HDU 4760 Good FireWall 完好Trie题解的更多相关文章

  1. HDU 4760 Good Firewall ( Trie树 )

    一开始看的时候就想歪了,比赛的时候一直在YY线段树区间覆盖,然后纠结节点数太多开不下怎么办啊啊啊啊…… 然后昨天吃饭的时候也在纠结这到底是个啥题,后来发现公共前缀->前缀??!!!!->这 ...

  2. HDU 1671 Phone List(Trie的应用与内存释放)

    Phone List Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  3. HDU 1251 统计难题(Trie模版题)

    统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others) Total Subm ...

  4. HDU 2846:Repository(Trie)

    http://acm.hdu.edu.cn/showproblem.php?pid=2846 题意:给出N个模式串,再给出M个文本串,问每一个文本串在多少个模式串中出现. 思路:平时都是找前缀的,这里 ...

  5. hdu 1251 统计难题(trie 树的简单应用)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1251 题意:给你多个字符串,求以某个字符串为前缀的字符串数量. 思路:简单的trie数应用,在trie ...

  6. 【hdu 3177 Crixalis's Equipment】 题解

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3177 \(describe\): 有一个山洞,山洞的容积最大为\(v\).现在你有\(n\)个物品,这 ...

  7. HDU 5687 Problem C(Trie+坑)

    Problem C Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Tota ...

  8. HDU 4099 Revenge of Fibonacci Trie+高精度

    Revenge of Fibonacci Problem Description The well-known Fibonacci sequence is defined as following: ...

  9. HDU 4758 Walk Through Squares ( Trie图 && 状压DP && 数量限制类型 )

    题意 : 给出一个 n 行.m 列的方格图,现从图左上角(0, 0) 到右下角的 (n, m)走出一个字符串(规定只能往下或者往右走),向右走代表' R ' 向下走则是代表 ' D ' 最后从左上角到 ...

随机推荐

  1. Java基础知识强化34:String类之String类的转换功能

    1. String类的转换功能 String[] split(String regex)//将字符串变成字符串数组(字符串切割) byte[] getBytes()//将字符串变成字节数组 char[ ...

  2. linux 常用find命令

    1.查找当前目录下以test开头的所有文件-会进入子目录中去查找 [root@rusky hgfs]# find -name test* 2.查找当前目录下名为test.txt的文件-会进入子目录中去 ...

  3. JAVA泛型解释

    理解Java泛型最简单的方法是把它看成一种便捷语法,能节省你某些Java类型转换(casting)上的操作: 1 List<Apple> box = ...; 2 Apple apple ...

  4. Css的三大机制(特性):特殊性、继承、层叠详解

    继承(Inheritance)是从一个元素向其后代元素传递属性值所采用的机制.确定应当向一个元素应用那些值时,用户代理(浏览器)不仅要考虑继承,还要考虑声明的特殊性(specificity),另外需要 ...

  5. .NET Core初体验 - 在Mac下运行第一个Web示例程序

    要说最近两天程序猿之间最喜欢吹水的事是什么?那绝壁是甲骨文要放弃Java!简直做梦都要笑醒!由于公司的产品线全面转向Java,最近几个月也一直在苦学Java技术.已经默默决定了,如果消息证实是真的,我 ...

  6. iOS调节系统音量

    目录[-] 使用MPVolumeView 编程实现系统音量调节2 通过MPVolumeSlider的实例来操作系统音量 有问题!我不喜欢系统弹出音量提示 还有问题,我修改了系统音量但是不是通过我的UI ...

  7. java读取网页

    package cn.stat.p4.ipdemo; import java.io.IOException; import java.io.InputStreamReader; import java ...

  8. (原)ubuntu下使用ftp软件

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6121663.html 参考网址: http://tieba.baidu.com/p/387426074 ...

  9. MySQL学习笔记(5) - 修改和删除数据库

    1.完整语句 ALTER {DATABASE | SCHEMA} [db_name] [DEFAULT] CHARACHER SET [=] charset_name; 2.修改数据库的编码方式 al ...

  10. HTML&CSS基础学习笔记1.14—有序列表及列表嵌套

    我们上篇讲到了无序列表,那么今天就来看看有序列表和他们的组合嵌套使用吧. 有序列表 现在我们要做那堆杂事了,但是发现这么多杂事,先做哪个好呢?于是我们给这堆杂事弄个优先级排序,让我们能够按照顺序做下去 ...