The 2021 ICPC Asia Regionals Online Contest (I) G Longest Prefix Matching (trie)

  • 题意:给你\(n\)个ip地址,以及长度和它所对应的next ip地址,有\(m\)个询问,在\(n\)个给定的ip地址中找到公共前缀大于所给长度并且最长的对应ip地址。(疯狂口胡)

  • 题解:每个ip地址有四个数,我们将其变成一个32位的数,然后建一颗trie树,直接找就行了。。。

  • 代码

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
    
    int n,m;
    int a,b,c,d;
    int len;
    char s[N][100];
    int trie[N][2];
    int cnt;
    int res[N];
    
    void insert(int x,int len,int id){
    	int p=0;
    	for(int i=31;i>=0;--i){
    		int now=0;
    		if((1<<i)&x) now=1;
    		if(!trie[p][now]) trie[p][now]=++cnt;
    		p=trie[p][now];
    		if(31-i+1==len){
    			res[p]=id;
    			return;
    		}
    	}
    }
    
    int query(int x){
    	int p=0;
    	int t=0;
    	for(int i=31;i>=0;--i){
    		int now=0;
    		if((1<<i)&x) now=1;
    		if(!trie[p][now]) return t;
    		p=trie[p][now];
    		if(res[p]) t=res[p];
    	}
    	return t;
    }
    
    int main() {
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%d.%d.%d.%d",&a,&b,&c,&d);
    		scanf("%d",&len);
    		scanf("%s",s[i]);
    		if(len==0) strcpy(s[0],s[i]);
    		int bi=(a<<24)|(b<<16)|(c<<8)|d;
    		insert(bi,len,i);
    	}
    	scanf("%d",&m);
    	for(int i=1;i<=m;++i){
    		scanf("%d.%d.%d.%d",&a,&b,&c,&d);
    		int bi=(a<<24)|(b<<16)|(c<<8)|d;
    		printf("%s\n",s[query(bi)]);
    	}
    
    
        return 0;
    }
    
    
上一篇:Defense:SMB协议漏洞利用与控制CVE-2017-7494("永恒之蓝")攻防实验


下一篇:Tower Defense Basic Pixel Art Pack 4.0