微软2016校园招聘4月在线笔试(二)403Forbidden
描述
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/30 deny 1.1.1.1 allow 127.0.0.1 allow 123.234.12.23/3 deny 0.0.0.0/0Each 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.
结题思路
一般来说最直接的解法就是通过预先存储所有规则然后读取请求的IP地址,并给出相应的YES和NO的规则,但是时间消耗为O(n),显然不满足要求。因此需要比Log(N)的解法,自然而然想到树结构,需要注意点有以下:
- 二进制表示的的数只有0和1,所以只要用二叉树的结构即可。
- 规则是有优先级的,即只要满足一条规则,即可返回相应的allow或者deny。所以在后续Request查询时需要比较该规则的先后关系。
- 如果规则是没有出现匹配的情况,返回YES。
- 如果规则的Mask为空字符串,则一切IP满足条件。
代码
using System;
using System.Linq;
using System.Text;
namespace Solution
{
class TriNode
{
public int Order { get; set; }
public String Status { get; set; }
public TriNode LefTriNode { get; set; }
public TriNode RightTriNode{ get; set; }public TriNode(string status="",int order=-1)
{
Status = status;
Order = order;
}
}
class TriTree
{
private readonly TriNode _root;public TriTree()
{
_root=new TriNode();
}public void InsertRule(string mask,int order,string status)
{
TriNode hot = _root;
for (int i = 0; i < mask.Length; i++)
{
if (mask[i] == '0')
{
if(hot.LefTriNode==null)
hot.LefTriNode=new TriNode();
hot = hot.LefTriNode;
if(hot.Status!="")
return;
}
else
{
if(hot.RightTriNode==null)
hot.RightTriNode=new TriNode();
hot = hot.RightTriNode;
if (hot.Status != "")
return;
}
}
hot.Status = status;
hot.Order = order;
}public string SearchRule(string ip)
{
int order = Int32.MaxValue;
string rule = string.Empty;
if (_root.Status != "")
{
order = _root.Order;
rule = _root.Status;
}
TriNode hot = _root;
int counter = 0;
while (counter<ip.Length)
{
if (ip[counter] == '0')
{
if(hot.LefTriNode==null)break;
hot = hot.LefTriNode;
if (hot.Status != "")
{
if (hot.Order < order)
{
order = hot.Order;
rule = hot.Status;
}
}
}
else
{
if(hot.RightTriNode==null)break;
hot = hot.RightTriNode;
if (hot.Status != "")
{
if (hot.Order < order)
{
order = hot.Order;
rule = hot.Status;
}
}
}
counter++;
}
return rule;
}
}
class Program
{
static void Main(string[] args)
{
int n = 0, m = 0;
Parsenm(ref n,ref m);
int counter = 0;
TriTree tree=new TriTree();
while (counter<n)
{
string line = Console.ReadLine();
string status = ParseStatus(line);
string mask = ParseMask(line);
tree.InsertRule(mask,counter,status);
counter++;
}
string[] res=new string[m];
counter = 0;
while (counter<m)
{
string line = Console.ReadLine();
string request = GetMask(line);
string tmp = tree.SearchRule(request);
res[counter] = string.IsNullOrEmpty(tmp)?"YES":tmp;
counter++;
}
foreach (var re in res)
{
Console.WriteLine(re);
}
}static void Parsenm(ref int n, ref int m)
{
string[] values = Console.ReadLine().Split(' ');
n = Convert.ToInt32(values[0]);
m = Convert.ToInt32(values[1]);
}static string ParseStatus(string line)
{
return line.Split(' ')[0] == "deny" ? "NO" : "YES";
}static string ParseMask(string line)
{
string ipMask = line.Split(' ')[1];
string ip;
int mask;
if (ipMask.Contains('/'))
{
ip = ipMask.Split('/')[0];
mask = Convert.ToInt32(ipMask.Split('/')[1]);
}
else
{
ip = ipMask;
mask = 32;
}
return GetMask(ip,mask);
}static string GetMask(string ip, int maskCount = 32)
{
string[] segments = ip.Split('.');
StringBuilder sb = new StringBuilder();
foreach (var segment in segments)
{
sb.Append((string) ToBinary(Convert.ToInt32(segment)));
}
return sb.ToString().Substring(0, maskCount);
}
private static string ToBinary(int value)
{
string binary = Convert.ToString(value, 2);
while (binary.Length != 8)
{
binary = binary.Insert(0, "0");
}
return binary;
}
}
}

浙公网安备 33010602011771号