-
题意:给你\(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; }