微软2016校招4月在线笔试——第二题 403Forbidden
2016-04-07 10:11
495 查看
http://hihocoder.com/problemset/problem/1289
↑↑↑ 题目原址
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
Little Hi runs a web server. Sometimes he has to deny access from a certain set of malicious IP addresses while his friends are still allow to access his server. To do this he writes N rules in the configuration
file which look like:
Each rule is in the form: allow | deny address or allow | deny address/mask.
When there comes a request, the rules are checked in sequence until the first match is found. If no rule is matched the request will be allowed. Rule and request are matched if the request address is the same as
the rule address or they share the same first mask digits when both written as 32bit binary number.
For example IP "1.2.3.4" matches rule "allow 1.2.3.4" because the addresses are the same. And IP "128.127.8.125" matches rule "deny 128.127.4.100/20" because 10000000011111110000010001100100
(128.127.4.100 as binary number) shares the first 20 (mask) digits with10000000011111110000100001111101 (128.127.8.125 as binary number).
Now comes M access requests. Given their IP addresses, your task is to find out which ones are allowed and which ones are denied.
Line 1: two integers N and M.
Line 2-N+1: one rule on each line.
Line N+2-N+M+1: one IP address on each line.
All addresses are IPv4 addresses(0.0.0.0 - 255.255.255.255). 0 <= mask <= 32.
For 40% of the data: 1 <= N, M <= 1000.
For 100% of the data: 1 <= N, M <= 100000.
For each request output "YES" or "NO" according to whether it is allowed.
样例输入
样例输出
我的代码:
思路:
定义结构体IPStruct { int first, second, third, forth, mask}, 其中所有初始值为0
分别提取rules进入allowrules数组和denyrules数组,
这里应该是有比较好的写法的,由于平时没怎么写过,所以只能靠纯手写最土的方法转换了。
在gets(rules[i])的过程中就判断,如果rules[i][0] == 'a',则 allowcnt++;否则,denycnt++;
gets完所有rules之后,初始化 1个容量为allowcnt 的 IPStruct 数组 allowrules, 再初始化一个容量为 denycnt 的 IPStruc t数组 denyrules。
分别提取rules进入两个数组,如果有‘/', 则 this.mask = '/'后面的数组转int; 否则 mask = -1。
然后提取request进入一个容量为M的IPStruct 数组
遍历两组rules进行match。
先遍历allowrules,若有符合,直接输出YES,continue入下一request;
若无allowrules match,则遍历denyrules,若matched,直接输出NO,continue入下一request;
若无matched,输出YES,continue入下一request。
match的过程是这样的。allow和deny的思路一样,只是输出为true和false的区别。以下以allow为例。
拿到一个request,首先进行遍历allowrules。
首先判断allowrules[i].mask != -1?,
{
若不等于,则代表含掩码
判断 rules[i] 是否 contain request。
是,返回 true。
否则
否,判断 判断allowrules[i]与request是否相等(isequal)。
是,返回 true。
否则
continue进入下一allowrules, i++
}
else
{
如果等于,则
判断allowrules[i]与request是否相等(isequal)。
是,返回 true。
否则
continue 进入下一 allowrules
}
同样 的结构遍历判断 deny rules, 是则返回false,不是则continue进入下一denyrules。
若能走到这里仍然未return,则return true(没有任何规则匹配,则允许)。
判断是否contain的思路是这样的。分别以<9,<17,<25,<33为界
if mask < 9
if (
a.first >> (8 - a.mask) == b.first >> (8 - a.mask) )
return true;
else
return false;
else if mask < 17
if (a.first != b.first)
return false;
else if ( a.second >> (16 - a. mask) == b.second >> (16 - a.mask) )
return true;
else
return false;
else if mask < 25
if (a.first != b.first || a.sencond != b.second)
return false;
else if .........
....
...
题目中的testcase是能够正确输出的,但是提交后为WA,不知道是哪种情况未考虑到呢。。。
另有其他更好的算法,希望能不吝赐教~~
↑↑↑ 题目原址
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
Little Hi runs a web server. Sometimes he has to deny access from a certain set of malicious IP addresses while his friends are still allow to access his server. To do this he writes N rules in the configurationfile which look like:
allow 1.2.3.4/30 deny 1.1.1.1 allow 127.0.0.1 allow 123.234.12.23/3 deny 0.0.0.0/0
Each rule is in the form: allow | deny address or allow | deny address/mask.
When there comes a request, the rules are checked in sequence until the first match is found. If no rule is matched the request will be allowed. Rule and request are matched if the request address is the same as
the rule address or they share the same first mask digits when both written as 32bit binary number.
For example IP "1.2.3.4" matches rule "allow 1.2.3.4" because the addresses are the same. And IP "128.127.8.125" matches rule "deny 128.127.4.100/20" because 10000000011111110000010001100100
(128.127.4.100 as binary number) shares the first 20 (mask) digits with10000000011111110000100001111101 (128.127.8.125 as binary number).
Now comes M access requests. Given their IP addresses, your task is to find out which ones are allowed and which ones are denied.
输入
Line 1: two integers N and M.Line 2-N+1: one rule on each line.
Line N+2-N+M+1: one IP address on each line.
All addresses are IPv4 addresses(0.0.0.0 - 255.255.255.255). 0 <= mask <= 32.
For 40% of the data: 1 <= N, M <= 1000.
For 100% of the data: 1 <= N, M <= 100000.
输出
For each request output "YES" or "NO" according to whether it is allowed.样例输入
5 5
allow 1.2.3.4/30 deny 1.1.1.1 allow 127.0.0.1 allow 123.234.12.23/3 deny 0.0.0.0/01.2.3.4
1.2.3.5
1.1.1.1
100.100.100.100
219.142.53.100
样例输出
YES YES NO YES NO
我的代码:
思路:
定义结构体IPStruct { int first, second, third, forth, mask}, 其中所有初始值为0
分别提取rules进入allowrules数组和denyrules数组,
这里应该是有比较好的写法的,由于平时没怎么写过,所以只能靠纯手写最土的方法转换了。
在gets(rules[i])的过程中就判断,如果rules[i][0] == 'a',则 allowcnt++;否则,denycnt++;
gets完所有rules之后,初始化 1个容量为allowcnt 的 IPStruct 数组 allowrules, 再初始化一个容量为 denycnt 的 IPStruc t数组 denyrules。
分别提取rules进入两个数组,如果有‘/', 则 this.mask = '/'后面的数组转int; 否则 mask = -1。
然后提取request进入一个容量为M的IPStruct 数组
遍历两组rules进行match。
先遍历allowrules,若有符合,直接输出YES,continue入下一request;
若无allowrules match,则遍历denyrules,若matched,直接输出NO,continue入下一request;
若无matched,输出YES,continue入下一request。
match的过程是这样的。allow和deny的思路一样,只是输出为true和false的区别。以下以allow为例。
拿到一个request,首先进行遍历allowrules。
首先判断allowrules[i].mask != -1?,
{
若不等于,则代表含掩码
判断 rules[i] 是否 contain request。
是,返回 true。
否则
否,判断 判断allowrules[i]与request是否相等(isequal)。
是,返回 true。
否则
continue进入下一allowrules, i++
}
else
{
如果等于,则
判断allowrules[i]与request是否相等(isequal)。
是,返回 true。
否则
continue 进入下一 allowrules
}
同样 的结构遍历判断 deny rules, 是则返回false,不是则continue进入下一denyrules。
若能走到这里仍然未return,则return true(没有任何规则匹配,则允许)。
判断是否contain的思路是这样的。分别以<9,<17,<25,<33为界
if mask < 9
if (
a.first >> (8 - a.mask) == b.first >> (8 - a.mask) )
return true;
else
return false;
else if mask < 17
if (a.first != b.first)
return false;
else if ( a.second >> (16 - a. mask) == b.second >> (16 - a.mask) )
return true;
else
return false;
else if mask < 25
if (a.first != b.first || a.sencond != b.second)
return false;
else if .........
....
...
题目中的testcase是能够正确输出的,但是提交后为WA,不知道是哪种情况未考虑到呢。。。
另有其他更好的算法,希望能不吝赐教~~
#include <iostream> #include <string> using namespace std; struct IPstruct { int sfirst, ssecond, sthird, sforth; int mask; }; IPstruct getRules(char* s); IPstruct GetIPs(char* s); bool Match(IPstruct req, IPstruct *denied, IPstruct *allowed, int deniedcnt, int allowcnt); bool validchar(char c) { if (c == '.' || c == '/') { return true; } else if (c >= '0' && c <= '9') { return true; } else return false; } IPstruct getRules(char *s) { IPstruct newIP; newIP.sfirst = 0; newIP.ssecond = 0; newIP.sthird = 0; newIP.sforth = 0; newIP.mask = 0; if (s[0] == 'd') { int i = 5; for (; validchar(s[i]) && s[i] != '.'; i++) { newIP.sfirst = newIP.sfirst*10 + s[i] - '0'; } for (i++; s[i] != '.'; i++) { newIP.ssecond = newIP.ssecond*10 + s[i] - '0'; } for (i++; s[i] != '.'; i++) { newIP.sthird = newIP.sthird*10 + s[i] - '0'; } for (i++; validchar(s[i]) && s[i] != '/'; i++) { newIP.sforth = newIP.sforth * 10 + s[i] - '0'; } if (s[i] == '/') { for (i++; validchar(s[i]); i++) newIP.mask = newIP.mask * 10 + s[i] - '0'; } else { newIP.mask = -1; } } else { int i = 6; for (; validchar(s[i]) && s[i] != '.'; i++) { newIP.sfirst = newIP.sfirst*10 + s[i] - '0'; } for (i++; s[i] != '.'; i++) { newIP.ssecond = newIP.ssecond*10 + s[i] - '0'; } for (i++; s[i] != '.'; i++) { newIP.sthird = newIP.sthird*10 + s[i] - '0'; } for (i++; validchar(s[i]) && s[i] != '/'; i++) { newIP.sforth = newIP.sforth * 10 + s[i] - '0'; } if (s[i] == '/') { for (i++; validchar(s[i]); i++) newIP.mask = newIP.mask * 10 + s[i] - '0'; } else { newIP.mask = -1; } } return newIP; } IPstruct GetIPs(char* s) { IPstruct newIP; newIP.sfirst = 0; newIP.ssecond = 0; newIP.sthird = 0; newIP.sforth = 0; newIP.mask = 0; int i = 0; for (; validchar(s[i]) && s[i] != '.'; i++) { newIP.sfirst = newIP.sfirst*10 + s[i] - '0'; } for (i++; s[i] != '.'; i++) { newIP.ssecond = newIP.ssecond*10 + s[i] - '0'; } for (i++; s[i] != '.'; i++) { newIP.sthird = newIP.sthird*10 + s[i] - '0'; } for (i++; validchar(s[i]) && s[i] != '/'; i++) { newIP.sforth = newIP.sforth * 10 + s[i] - '0'; } if (s[i] == '/') { for (i++; validchar(s[i]); i++) newIP.mask = newIP.mask * 10 + s[i] - '0'; } else { newIP.mask = -1; } return newIP; } bool isequal(const IPstruct& a, const IPstruct& b) { if (a.sfirst == b.sfirst && a.ssecond == b.ssecond && a.sthird == b.sthird && a.sforth == b.sforth) return true; else return false; } bool iscontain(const IPstruct& a, const IPstruct& b) { if (a.mask < 9) { if( (a.sfirst >> (8 - a.mask)) == (b.sfirst >> (8 - a.mask)) ) return true; else return false; } else if (a.mask < 17) { if (a.sfirst != b.sfirst) { return false; } else if ( (a.ssecond >> (16 - a.mask)) == (b.ssecond >> (16 - a.mask)) ) { return true; } else return false; } else if (a.mask < 25) { if (a.sfirst != b.sfirst || a.ssecond != b.ssecond) { return false; } else if ( (a.sthird >> (24 - a.mask)) == (b.sthird >> (24 - a.mask)) ) { return true; } else return false; } else if (a.mask < 33) { if ( a.sfirst != b.sfirst || a.ssecond != b.ssecond || a.sthird != b.sthird) { return false; } else if ( (a.sforth >> (32 - a.mask)) == (b.sforth >> (32-a.mask)) ) { return true; } else return false; } else { return false; } } bool Match(IPstruct req, IPstruct *denied, IPstruct *allowed, int deniedcnt, int allowcnt) { for (int i = 0; i < allowcnt; i++) { if (allowed[i].mask != -1) { if (iscontain(allowed[i], req)) { return true; } else if (isequal(req, allowed[i])) { return true; } else continue; } else { if (isequal(req, allowed[i])) { return true; } } } for (int i = 0; i < deniedcnt; i++) { if (denied[i].mask != -1) { if (iscontain(denied[i], req)) { return false; } else if (isequal(req, denied[i])) { return false; } else continue; } else { if (isequal(req, denied[i])) { return false; } } } return true; } int main() { int N, M; int deniedcnt = 0, allowcnt = 0; cin >> N >> M; char **rules, **request; rules = new char* ; request = new char* [M]; char *t = new char[2]; gets(t); for (int i = 0; i < N; i++) { rules[i] = new char [256]; gets(rules[i]); if (rules[i][0] == 'd') { deniedcnt++; } else { allowcnt++; } } IPstruct *denied = new IPstruct [deniedcnt]; IPstruct *allowed = new IPstruct [allowcnt]; for (int j = 0; j < M; j++) { request[j] = new char [256]; gets(request[j]); } int deniedindex = 0, allowindex = 0; for (int i = 0; i < N; i++) { if (rules[i][0] == 'd') { denied[deniedindex++] = getRules(rules[i]); } else { allowed[allowindex++] = getRules(rules[i]); } } for (int i = 0; i < M; i++) { if (Match(GetIPs(request[i]), denied, allowed, deniedcnt, allowcnt)) { cout << "YES" << endl; } else { cout << "NO" << endl; } } return 0; }
相关文章推荐
- Linux下mongodb的安装及启动
- USACO holstein AC code
- C# DataGridView导出Excel的两种经典方法
- 贪心算法 problemD
- ajaxFileUpload返回的json数据带<pre>标签,导致无法执行success后面的代码
- Android 开发最佳实践
- Spark 临时记录
- android软键盘弹出引起的各种不适终极解决方案
- 交叉编译arm gdb
- simcom7100c在ubuntu下移动宽带mobile broadband上网
- C++作业2
- linux修改硬盘已挂载目录
- Android学习笔记函数
- Tomcat与jdk在Linux上的安装与配置
- syntaxhighlighter的使用
- Adobe Acrobat X Pro 10.1.0关闭自动更新的方法
- Counting Bits
- C++之类的比较运算符的重载
- activiti自定义流程之Spring整合activiti-modeler5.16实例(七):任务列表展示
- MYSQL中取当前周/月/季/年的第一天与最后一天