微软2016校招4月在线笔试——第二题 403Forbidden

来源:互联网 发布:miss7号淘宝店 编辑:程序博客网 时间:2024/05/17 09:42

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:

allow 1.2.3.4/30deny 1.1.1.1allow 127.0.0.1allow 123.234.12.23/3deny 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 5allow 1.2.3.4/30deny 1.1.1.1allow 127.0.0.1allow 123.234.12.23/3deny 0.0.0.0/01.2.3.41.2.3.51.1.1.1100.100.100.100219.142.53.100
样例输出
YESYESNOYESNO
我的代码:

思路:

定义结构体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;}elsereturn 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;elsereturn 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;}elsereturn 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;}elsereturn 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;}elsereturn 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;}elsecontinue;}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;}elsecontinue;}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* [N];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;}


)



0 0