2016年4月微软在线笔试第二题-403 forbidden
2016-04-15 20:15
197 查看
本地运行没有错误,提交上去以后反馈RE,实在想不通,求大神帮看/(ㄒoㄒ)/~~
哈哈哈哈,仰天苦笑三声,胡汉三又回来啦。后面debug了一下,搞了两天终于找到错误的原因了,原来
这一句,写了可空指针,笨呐,然后解决方案是给输出结果的数组output[j]赋初值“YES”,因为如果没有一个rules match,那就是“YES”
后面改了代码后,提交上去还是wrong answer,说明,我有只考虑了一部分测试数据,还有更多的数据是错的,在网上寻求帮助后,终于看到了一位网友的提点:并没有符合一旦match rules即跳出匹配的条件。于是,我重写了request这个方法,变成,每次只判断一行rule与该request是否匹配。而我一直找不到一个条件,用来判断如果没有rules匹配成功,怎么给output数组赋“YES”,后来,我就想到了一个,本人认为,是这个程序里面唯一的亮点(哭),加了个return “noMatch”,这个字符串来决定,请求是否匹配上rules,因为不管是allow还是deny,都是匹配,只不过匹配后返回的信息不同,这也是后面舍弃将allow和deny分别装在两个链表的原因。
更改后的代码,提交后是time limited error,有人提议用前缀树、后缀树减小复杂度,实在改不动了。一个代码,改出七八个bug,花了一个星期,我也真是差劲。
import java.util.ArrayList; import java.util.Scanner; public class Main { int allowS = 0;//rules allow数组大小 int denyS = 0; ArrayList<String> allow = new ArrayList<>();//用来存放动态变化的rules,整个类都要使用,则定义为实例变量 ArrayList<String> deny = new ArrayList<>(); public static void main(String[] args) { Scanner input = new Scanner(System.in); int N = input.nextInt(); int M = input.nextInt(); Main webser = new Main(); if(1<=N && M<=100000){ webser.rules(N); String[] output = webser.request(M); for(int j=0;j<output.length;j++){ System.out.println(output[j]); } //sca.close();//写完之后就要close,否则容易忘记 } input.close(); } /* * @param n为rules个数,此方法用来封装rules */ public void rules(int n){ @SuppressWarnings("resource") Scanner sca = new Scanner(System.in); for(int i=0;i<n;i++){ String s = sca.nextLine(); String[] rule = s.split(" ");//返回字符串数组 if(rule[0].equals("allow")){ allow.add(rule[1]); allowS++; }else if(rule[0].equals("deny")){ deny.add(rule[1]); denyS++; } } //sca.close();如果把这个流关闭了,再调用request方法中的输入流就不行了 } public String[] request(int m){ //开始匹配,最优的应该是用正则表达式匹配,稍后优化 String[] output1 = new String[m];//没问题 String[] requ = new String[m];//创建请求数组 @SuppressWarnings("resource") Scanner sca = new Scanner(System.in); for(int i=0;i<m;i++){ requ[i] = sca.nextLine();//输入请求ip数组 } //开始遍历每一次request是否符合命中rules circle: for(int j=0;j<m;j++){ for(int k=0;k<allow.size();k++){ if(requ[j].equals(allow.get(k))){ output1[j] = "YES";//return "YES"; continue circle; }else if(allow.get(k).contains("/")){ String requBinary =IPtoInt.ipToint(requ[j]); String[] allowip = allow.get(k).split("/"); int mask =Integer.parseInt(allowip[1]);//取位数 String allowstr = IPtoInt.ipToint(allowip[0]); //String allowMask = allowstr.substring(0,mask);//变成字符串后,取前几位 if(requBinary.substring(0, mask).equals(allowstr.substring(0,mask))){ output1[j] = "YES";//return "YES"; continue circle; } } } for(int k=0;k<deny.size();k++){ if(requ[j].equals(deny.get(k))){ output1[j] = "NO";//return "NO"; continue circle; }else if(deny.get(k).contains("/")){ String requBinary = IPtoInt.ipToint(requ[j]); String[] denyip = deny.get(k).split("/"); int mask = Integer.parseInt(denyip[1]); String denystr = IPtoInt.ipToint(denyip[0]); String denyMask = denystr.substring(0,mask); if((requBinary.substring(0,mask)).equals(denyMask)){//必须对比前mask位 output1[j] = "NO";//return "NO"; continue circle; } } } if(output1[j].length()==0) output1[j] = "YES"; } //sca.close(); return output1;//返回字符串数组 } } class IPtoInt { // 重写了方法,将ip地址转换为二进制。 public static String ipToint(String strIP) { String[] ip = new String[4]; String zero = "00000000";//用来补位的 String[] ipstr = strIP.split("\\."); // 将每个.之间的字符串转换成整型 ip[0] = Integer.toBinaryString(Integer.parseInt(ipstr[0])); ip[1] = Integer.toBinaryString(Integer.parseInt(ipstr[1])); ip[2] = Integer.toBinaryString(Integer.parseInt(ipstr[2])); ip[3] = Integer.toBinaryString(Integer.parseInt(ipstr[3])); for(int i=0;i<4;i++){ if(ip[i].length()<8){ ip[i] =zero.substring(0,8-ip[i].length()) + ip[i];//如果每一段ip不足八位,那么用字符串加法高位补0,不用循环,一次性补0,因为ip.length()一直会变 } } return ip[0]+ip[1]+ip[2]+ip[3]; } }
哈哈哈哈,仰天苦笑三声,胡汉三又回来啦。后面debug了一下,搞了两天终于找到错误的原因了,原来
if(output1[j].length()==0) output1[j] = "YES";
这一句,写了可空指针,笨呐,然后解决方案是给输出结果的数组output[j]赋初值“YES”,因为如果没有一个rules match,那就是“YES”
后面改了代码后,提交上去还是wrong answer,说明,我有只考虑了一部分测试数据,还有更多的数据是错的,在网上寻求帮助后,终于看到了一位网友的提点:并没有符合一旦match rules即跳出匹配的条件。于是,我重写了request这个方法,变成,每次只判断一行rule与该request是否匹配。而我一直找不到一个条件,用来判断如果没有rules匹配成功,怎么给output数组赋“YES”,后来,我就想到了一个,本人认为,是这个程序里面唯一的亮点(哭),加了个return “noMatch”,这个字符串来决定,请求是否匹配上rules,因为不管是allow还是deny,都是匹配,只不过匹配后返回的信息不同,这也是后面舍弃将allow和deny分别装在两个链表的原因。
更改后的代码,提交后是time limited error,有人提议用前缀树、后缀树减小复杂度,实在改不动了。一个代码,改出七八个bug,花了一个星期,我也真是差劲。
import java.util.Scanner; //微软笔试第二题 403 forbidden,第四版,改变存放rules结构,不把allow和deny分开,按rules顺序匹配(字符串匹配处理,未加前缀树),时间复杂度粗略估计为o(n^3) public class Main { Main(Scanner in){ int N = in.nextInt(); int M = in.nextInt(); @SuppressWarnings("unused") String delete = in.nextLine(); if(1<=N && M<=100000){ String[] rules = new String ;//读取rules数组 for(int i=0;i<N;i++){ rules[i] = in.nextLine(); } String[] request = new String[M];//读取request数组 for(int j=0;j<M;j++){ request[j] = in.nextLine(); } /* * @param output[]为输出结果 */ String[] output = new String[M]; for(int j=0;j<M;j++){ for(int i =0;i<N;i++){ output[j]=matchRules(request[j], rules[i]); if(output[j].equals("noMatch")){ output[j] = "YES"; continue; }else{ break; } } System.out.println(output[j]); } } in.close(); } public static void main(String[] args) { Scanner in = new Scanner(System.in); @SuppressWarnings("unused") Main forbidden = new Main(in); } /* * @param n为rules个数,此方法用来封装rules * @param s为每一行读取的rules string */ public String matchRules(String request,String rules){ String[] ruleSplit = rules.split(" ");//把rules前面的标记和ip分割 if(ruleSplit[0].equals("allow")){ if(request.equals(ruleSplit[1])){ return "YES"; }else if(ruleSplit[1].contains("/")){ String requBina = IPtoInt.ipToint(request); String[] ruleSplit2 = ruleSplit[1].split("/");//rule后面有/的分割 int mask = Integer.parseInt(ruleSplit2[1]); String ruleBina = IPtoInt.ipToint(ruleSplit2[0]); if(requBina.substring(0,mask).equals(ruleBina.substring(0,mask))){ return "YES"; } } }else if(ruleSplit[0].equals("deny")){ if(request.equals(ruleSplit[1])){ return "NO"; }else if(ruleSplit[1].contains("/")){ String requBina = IPtoInt.ipToint(request); String[] ruleSplit2 = ruleSplit[1].split("/");//rule后面有/的分割 int mask = Integer.parseInt(ruleSplit2[1]); String ruleBina = IPtoInt.ipToint(ruleSplit2[0]); if(requBina.substring(0,mask).equals(ruleBina.substring(0,mask))){ return "NO"; } } } return "noMatch"; } } class IPtoInt { // 重写了方法,将ip地址转换为二进制。这个方法不错,比原方法简单 public static String ipToint(String strIP) { String[] ip = new String[4]; String zero = "00000000";//用来补位的 String[] ipstr = strIP.split("\\."); //整形转换为字符串二进制,tobinarystring这个函数本身,就不会补八位 ip[0] = Integer.toBinaryString(Integer.parseInt(ipstr[0])); ip[1] = Integer.toBinaryString(Integer.parseInt(ipstr[1])); ip[2] = Integer.toBinaryString(Integer.parseInt(ipstr[2])); ip[3] = Integer.toBinaryString(Integer.parseInt(ipstr[3])); for(int i=0;i<4;i++){ if(ip[i].length()<8){ ip[i] =zero.substring(0,8-ip[i].length()) + ip[i];//如果每一段ip不足八位,那么用字符串加法高位补0,不用循环,一次性补0,因为ip.length()一直会变 } } return ip[0]+ip[1]+ip[2]+ip[3]; } }
相关文章推荐
- 泛型类的定义与使用
- 半平面交初级
- 环境——卸载redhat6.5的yum,安装centos6的yum,配置第三房yum源
- java第五次作业
- iOS小技巧 - 选择编译
- HDU 3367 Pseudoforest(最大生成树+并查集)
- Fragment嵌套ViewPager,viewpager切换的时候,手机出现白屏
- 泛型
- Android学习之Android 5.0分享动画实现微信点击全屏效果
- Python3.5.1 百度翻译代码
- 'hibernate.dialect' must be set when no Connection avalable
- iOS 8 系统自带BlurEffect 毛玻璃特效
- 求两个有序数组的共有元素
- 欢迎使用CSDN-markdown编辑器
- 面试题:什么叫B树
- golang append
- 什么是I2C通信
- NumPy的详细教程
- MySQL日期时间函数大全 转
- Error: could not open `C:\Program Files\Java\jre6\lib\i386\jvm.cfg'