首页 > 试题广场 >

IP过滤器

[编程题]IP过滤器
  • 热度指数:389 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
在搜索引擎后端服务中,需要对恶意的抓取进行限制,其中的一个环节即对访问IP进行限制。请设计一个IP过滤器,实现对访问的IP限制的功能。对IP的限制数据有三种格式:
1.全IP:如222.205.58.16
2.前面带 *:如 *.58.16
3.后面带 *:如 222.205.58.*
带 * 的表示匹配到任意的IP段均可,且 * 可以代表多个ip段,且 * 只能出现在开头或者结尾。
现给出若干条需要过滤的规则,以及若干输入的IP,你需要输出这若干条IP是否会被过滤

输入描述:
输入的第一行是过滤规则的条数N和需要过滤的IP数量M,之后的N行为IP的过滤规则且均合法,再之后的M行为需要进行判断是否被过滤的IP。其中N<100,M<50。


输出描述:
0:该条IP不会被过滤
1:该条IP会被过滤
总共M条需要判断的IP需要以空格作为区分
示例1

输入

5 3
222.205.58.16
*.58.16
222.205.58.*
*.16
224.*
222.205.58.17
222.205.59.19
223.205.59.16

输出

1 0 1

说明

由于222.205.58.17这个IP匹配到222.205.58.*这条过滤规则,222.205.59.19没有匹配到任何过滤规则,223.205.59.16匹配到*.16这条过滤规则,所以输出1 0 1
/**
 * 前缀 后缀 的匹配问题 easy
 */

import java.util.Scanner;
 
public class Main {
 
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
 
        int N = sc.nextInt();
        int M = sc.nextInt();
 
        sc.nextLine();
 
        //读取规则
        String[] patterns = new String[N];
        for(int i =0 ;i < N;i++){
            patterns[i] = sc.nextLine();
        }
 
        //读取IP
        String[] IPs = new String[M];
        for(int i = 0;i < M; i++){
            IPs[i] = sc.nextLine();
        }
 
        //暴力匹配
        for(int i = 0; i < IPs.length;i++){
            boolean lock = false;
            for(int j = 0; j < patterns.length;j++){
                String t = "";
                if(patterns[j].charAt(0) == '*'){
                    t = patterns[j].replace("*","");
                    if(IPs[i].endsWith(t)){
                        System.out.print(1 + " ");
                        lock = true;
                        break;
                    }
                }else if(patterns[j].charAt(patterns[j].length()-1) == '*'){
                    t = patterns[j].replace("*","");
                    if(IPs[i].startsWith(t)){
                        System.out.print(1 + " ");
                        lock = true;
                        break;
                    }
                }else{
 
                    if(patterns[j].equals(IPs[i])){
                        System.out.print(1 + " ");
                        lock = true;
                        break;
                    }
                }
            }
            if(lock == false){
                System.out.print(0 + " ");
            }
        }
    }
}

发表于 2020-08-11 22:49:22 回复(0)
说实话,这题用字典树Trie比较好。
#include<bits/stdc++.h>
using namespace std;
unordered_map<char,int> mp={{'.',10},{'*',11}};
struct Node
{
    bool is_End;
    Node* son[12];
    Node()
    {
        is_End=false;
        for(int i=0;i<12;i++)
            son[i]=NULL;
    }
}*root;
void insert(Node *p,string & str)
{
    for(int i=0;i<str.size();i++)
    {
        int u=isdigit(str[i])?(str[i]-'0'):mp[str[i]];
        if(!p->son[u])    p->son[u]=new Node();
        p=p->son[u];
    }
    p->is_End=true;
}
bool search(Node *p,string &str)
{
    for(int i=0;i<str.size();i++)
    {
        int u=isdigit(str[i])?(str[i]-'0'):mp[str[i]];
        if(!p->son[u])   return false;
        p=p->son[u];
        if(p->son[11])    return true;
    }
    return p->is_End;
}
int main()
{
    int N,M;
    while(cin>>N>>M)
    {
        root=new Node();
        string str;
        for(int i=0;i<N;i++)
        {
            cin>>str;
            insert(root,str);
            reverse(str.begin(),str.end());
            insert(root,str);
        }
        int ans;
        for(int i=0;i<M;i++)
        {
            ans=0;
            cin>>str;
            ans= ans || search(root,str);
            reverse(str.begin(),str.end());
            ans= ans || search(root,str);
            cout<<ans<<" ";
        }
    }
    return 0;
}


编辑于 2020-09-04 17:05:10 回复(0)
有一说一这题用python写是真的简单粗暴
import re

# main function
def main():
    N, M = map(int, input().split(' '))
        
        # 规则列表
    rule = []
        
        # IP列表
    ip = []

        # 结果列表
    res = []

        # 构建规则列表时将规则转化成正则表达式
        # 简单粗暴一点来说,就是将IP字段中的'.'换成'\.',将'*'换成'.*'
        # 举个简单的例子:'192.168.1.*'转换成正则表达式可以写成'192\.168\.1\..*'
        # 这样就可以直接进行匹配了
    for i in range(0, N):
        rule.append(input().replace('.', '\.').replace('*', '.*'))

    for i in range(0, M):
        ip.append(input())

    for i in ip:
        x = 0
        for j in rule:
            try:
                t = re.search(j, i)
                if t.group() == i:
                    x = 1
                    break
            except Exception:
                pass
        res.append(x)
    
    out = ""
    for i in res:
        out += "{} ".format(i)
    print(out)

if  __name__ == "__main__":
    main()

发表于 2020-09-25 09:55:12 回复(0)
把取到的*都去掉,在第一个的话,就把后面的值memmove上来,在最后就把*变成0。
所有的条件规则都放在rule数组里面
每次输入一个就strstr判断,如果有重复就输出1,否则输出0.
#include <iostream>
#include <string.h>
using namespace std;

class IP
{
    int N;
    int M;
public:
    IP(int M=0,int N=0)
    {
        this->N = N;
        this->M = M;
    }
    void get_ip(void)
    {
        char** rule =new char*[M];
        for(int i=0; i<M; i++)
        {
            rule[i] = new char[16];
            cin >> rule[i];
            if(rule[i][0] == '*')
            {
                memmove(&rule[i][0],&rule[i][1],16);
                continue;
            }
            int len = strlen(rule[i]);
            if(rule[i][len-1] == '*')
            {
                rule[i][len-1] = 0;
            }
        }
        char ip[16] = {};
        bool flag = false;
        for(int i=0; i<N; i++)
        {
            cin>>ip;
            for(int i=0;i<M; i++)
            {
                if(NULL != strstr(ip,rule[i])) 
                {
                    flag = true;
                }
            }
            if(flag) cout<<"1 ";
            else cout <<"0 ";
            flag = false;
        }
    }
};

int main()
{
    int M=0;
    int N=0;
    cin>>M>>N;
    IP ip(M,N);
    ip.get_ip();
}

发表于 2020-09-24 20:16:55 回复(0)
//使用正则表达式
regex1 = "222.205.58.16";
regex2 = ".*(58.16)";
regex3 = "(222.205.58).*";
String str1;
boolean res1 = str1.matches(regex1 | regex1 | regex1);
发表于 2020-09-25 17:44:30 回复(0)
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int solution(string str1[],string str2,int m)
{
	int j=0,k=0;
	for (int i = 0; i < m; i++)
	{
		// 判断规则中是否有*号存在
		if (str1[i].find('*') == string::npos)
		{
			if(str1[i].compare(str2) == 0)
				return 1; // 过滤掉了
		}
		else if (str1[i].find('*') == 0)
		{
			// * 号在前,从后往前比
			j = str1[i].size()-1;
			k = str2.size()-1;
			for(;j>=0,k>=0;j--,k--)
			{
				if (str1[i].c_str()[j] != str2.c_str()[k])
					break;				
			}			
		}
		else
		{
			// * 号在后,从前往后比
			j=0,k=0;
			for(;j<=str1[i].size()-1,k<=str2.size()-1;j++,k++)
			{
				if (str1[i].c_str()[j] != str2.c_str()[k])		
					break;				
			}			
		}
		if (str1[i].c_str()[j] == '*')
		{
			return 1; // 如果只有*不等表示其他都一样还是要过滤掉
		}
	}
	return 0;// 循环结束后都不符合要求表示不过滤掉

}
int  main()
{
	int m,n;// m 规则,n条数
	cin>>m;
	cin>>n;
	string * arr1 = new string[m];// m 条规则
	string  * arr2 = new string[n];// n 条ip
	int * arr = new int[n];
	for (int i = 0; i < m; i++)
	{
		cin>>arr1[i];
	}
	for (int j = 0; j < n; j++)
	{
		cin>>arr2[j];
	}
	for (int k = 0; k < n; k++)
	{
		arr[k]= solution(arr1,arr2[k],m);
		cout<<arr[k]<<" ";
	}
	cout<<endl;
	return 0;
}

发表于 2020-08-25 18:23:35 回复(0)
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int N = in.nextInt();
        int M = in.nextInt();
        String[] ip = new String[M];
        String[] strs = new String[N];
        int[] boo = new int[M];
        for (int i = 0; i < N; i++) {
            strs[i] = in.next();
        }
        for (int i = 0; i < M; i++) {
            ip[i] = in.next();
        }
        for (int i = 0;i<N;i++){
            if (strs[i].startsWith("*")){
                strs[i] = strs[i].substring(1);
            }
            if (strs[i].endsWith("*")){
                strs[i] = strs[i].substring(0,strs[i].length()-1);
            }
        }
        for (int i =0;i<M;i++){
            for (int j =0;j<N;j++){
                if (ip[i].contains(strs[j])) boo[i] = 1;
            }
        }
        for(int b:boo){
            System.out.print(b+" ");
        }
    }
}

发表于 2020-08-25 12:10:02 回复(1)
将IP与过滤器一一比较,有*号存在直接不好比较,将ip拆成4段进行比较
importjava.util.Scanner;
 
publicclassMain {
    publicstaticvoidmain(String[] args){
        Scanner in=newScanner(System.in);
        intm,n;
        m=in.nextInt();
        n=in.nextInt();
        String[] ip_filter=newString[m];
        for(inti = 0; i <m ; i++) {
            ip_filter[i]=in.next();
        }
        for(inti = 0; i <n ; i++) {
            String ip=in.next();
            String[] str=ip.split("\\.");
            intt=0;
            for(intj = 0; j <m ; j++) {
                String[] strs=ip_filter[j].split("\\.");
                if(strs.length==4){
                    ints=0;
                    for(intk = 0; k <4; k++) {
                        if(!str[k].equals(strs[k]) && !strs[k].equals("*")){
                            t++;break;
                        }
                        s++;
                    }
                    if(s==4){System.out.print(1);
                        System.out.print(" ");break;}
                }
                elseif(strs.length==3&&strs[0].equals("*")){
                    if(!strs[1].equals(str[2]) || !strs[2].equals(str[3]))
                        t++;
                    else{System.out.print(1);
                        System.out.print(" ");break;}
                }
                    elseif(strs.length==3&&strs[2].equals("*")){
                    if(!strs[0].equals(str[0]) || !strs[1].equals(str[1]))
                        t++;
                    else{System.out.print(1);
                        System.out.print(" ");break;}
                    }
                    elseif(strs.length==2&& strs[0].equals("*")) {
                    if(!strs[1].equals(str[3]))
                        t++;
                    else{System.out.print(1);
                        System.out.print(" ");break;}
                }
                elseif(strs.length==2&& strs[1].equals("*")) {
                    if(!strs[0].equals(str[0]))
                        t++;
                    else{System.out.print(1);
                        System.out.print(" ");break;}
                }
 
            }
            if(t==m) {System.out.print(0);
            System.out.print(" ");}
        }
}
}

发表于 2020-08-02 23:17:42 回复(0)


import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int m=sc.nextInt();
        int n=sc.nextInt();  String[] strs=new String[n];
    sc.nextLine();
    for(int i=0;i<m;i++)pattern[i]=sc.nextLine();
    for(int i=0;i<n;i++)strs[i]=sc.nextLine();
    for(int i=0;i<n;i++){
        boolean flag=true;
        String s=strs[i];
        for(int j=0;j<m;j++){
            if(isMatch(s,pattern[j],0,0)){
                System.out.print(1+" ");
                flag=false;
                break;
            }
        }
        if(flag)System.out.print(0+" ");
    }

}
public static boolean isMatch(String s,String p,int i,int j){
    String[] ss=s.split("\\.");
    String[] ps=p.split("\\.");
    if(i==ss.length){
        while(j<ps.length && ps[j].equals("*"))j++;
        return j==ps.length;
    }
    if(ps[j].equals("*")){
        return isMatch(s,p,i+1,j) || isMatch(s,p,i,j+1);
    }
    return ss[i].equals(ps[j]) && isMatch(s,p,i+1,j+1);
}

}

编辑于 2020-07-28 19:50:45 回复(0)
新建Node类,把所有规则用数组存起来,逐个比较
import java.util.*;

class Node {
    String a;
    String b;
    String c;
    String d;

    Node (String v1, String v2) {
        if (v1.equals("*")) {
            a = "0";
            b = "0";
            c = "0";
            d = v2;
        } else {
            a = v1;
            b = "0";
            c = "0";
            d = "0";
        }
    }

    Node (String v1, String v2, String v3) {
        if (v1.equals("*")) {
            a = "0";
            b = "0";
            c = v2;
            d = v3;
        } else if (v3.equals("*")) {
            a = v1;
            b = v2;
            c = "0";
            d = "0";
        }
    }

    Node (String v1, String v2, String v3, String v4) {
        if (v1.equals("*")) {
            a = "0";
            b = v2;
            c = v2;
            d = v3;
        } else if (v4.equals("*")) {
            a = v1;
            b = v2;
            c = v3;
            d = "0";
        } else {
            a = v1;
            b = v2;
            c = v3;
            d = v4;
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        Node[] arr = new Node[n];
        for (int i = 0; i < n; i++) {
            String input = sc.next();
            String[] cur = input.split("\\.");
            if (cur.length == 4) {
                arr[i] = new Node(cur[0], cur[1], cur[2], cur[3]);
            } else if (cur.length == 3) {
                arr[i] = new Node(cur[0], cur[1], cur[2]);
            } else if (cur.length == 2) {
                arr[i] = new Node(cur[0], cur[1]);
            }
        }
        for (int i = 0; i < m; i++) {
            String input = sc.next();
//            System.out.println(input);
            String[] cur = input.split("\\.");
//            System.out.println(Arrays.toString(cur));
            Node node = new Node(cur[0], cur[1], cur[2], cur[3]);
            boolean res = false;
            for (int j = 0; j < n; j++) {
                if ((node.a.equals(arr[j].a) || arr[j].a.equals("0")) && (node.b.equals(arr[j].b) || arr[j].b.equals("0")) &&
                        (node.c.equals(arr[j].c) || arr[j].c.equals("0")) && (node.d.equals(arr[j].d) || arr[j].d.equals("0"))) {
                    res = true;
                    break;
                }
            }
            if (res) {
                System.out.print(1 + " ");
            } else {
                System.out.print(0 + " ");
            }
        }
    }
}
发表于 2020-07-27 15:22:31 回复(0)
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
 
public class Main {
    public static void main(String[] args) {
//        String[] s1 = {"222","205","58","17"};
//        String[] s2 = {"222","205","58","*"};
//        System.out.println(pass(s1, s2)?1:0);
 
        Scanner scanner;
        List<String[]> list = new ArrayList<String[]>();
        int n, m;
        String temp;
        String[] split;
        scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();
        temp = scanner.nextLine();
//        System.out.println("开始:"+temp.length());
        for(int i=0; i<n; i++){
            temp = scanner.nextLine();
            split = temp.split("\\.");
//            System.out.println(temp+split.length);
            list.add(split);
        }
 
        for(int i=0; i<m; i++){
            temp = scanner.nextLine();
            split = temp.split("\\.");
//            System.out.println(temp+split.length);
            System.out.print(isPass(split, list)?1+" ":0+" ");
        }
    }
    public static boolean isPass(String[] split, List<String[]> list){
        for(String[] sps:list){
            if(pass(split,sps)){
                return true;
            }
        }
        return false;
    }
    public static String[] removeStrings(String[] strs, int index){
        if(index<0||index>=strs.length){
            return null;
        }
        if(strs.length==0){
            return new String[0];
        }
        String[] res = new String[strs.length-1];
        int resIndex = 0;
        if(strs.length>1){
            for(int i=0; i< strs.length; i++){
                if(i != index){
                    res[resIndex ++] = strs[i];
                }
            }
        }
        return res;
    }
    public static boolean pass(String[] split, String[] sps){
        if(split.length == 0&& sps.length == 0){
            return true;
        }
        if(sps.length==0&&split.length!=0){
            return false;
        }
        if("*".equals(sps[0])){
            if(split.length==0){
                return pass(split,removeStrings(sps,0));
            }
            return pass(removeStrings(split,0),sps)||
                    pass(split,removeStrings(sps,0));
        }
        if(split.length!=0 && split[0].equals(sps[0])){
//            System.out.println("s1"+split[0]+"s2:"+sps[0]);
            return pass(removeStrings(split,0),
                    removeStrings(sps,0));
        }
        return false;
    }
 
}
suceess!
发表于 2020-07-15 20:10:28 回复(0)
n, m = input().split(' ')
n = int(n)
m = int(m)
s = set()
suffix = set()
for i in range(n):
    ip = tuple(input().split('.'))
    if ip[0] == '*':
        suffix.add(ip[1:])
    elif ip[-1] == '*':
        s.add(ip[:-1])
    else:
        s.add(ip)
 
#print(s)
#print(suffix)
res = []
for j in range(m):
    #l = input().split('.')
    ip = tuple(input().split('.'))
    length = len(ip)
    flag = True
    for i in range(1, length+1):
        #print(ip[:i])
        if ip[:i] in s:
            flag = False
    for i in range(0, length):
        #print(ip[i:])
        if ip[i:] in suffix:
            flag = False
    if flag:
        res.append(0)
    else:
        res.append(1)
         
for i in range(len(res)):
    if i != len(res)-1:
        print(res[i], end=' ')
    else:
        print(res[i])

运行时间: 30 ms 占用内存:3472K
发表于 2020-07-08 18:07:51 回复(0)