G Longest Prefix Matching(字典树ipv6匹配)
题目大意
先给出n条数据,每条数据包括一个ip地址,需要匹配的长度len,以及应返回的ip地址。之后给出m次询问,每次询问给出一个ip地址,在已有的ip地址中寻找最长的能完成匹配的ip地址,这里的匹配指转换为32位二进制数后,前len位数字相等。注意:这里是至少要len,然后是越长越好
题目解析
这里吧每一个ip地址转化为一个数,对于给出的n条数据可以把它们的前len位加入到trie中,并在结尾处节点打上标记cnt,cnt[i]记录以i节点结尾的01串对应的ip地址编号(答案串的编号),对于m次询问,把每个询问串转为01二进制后,query一遍得到最长的匹配位置即可。本题主要是处理读入数据比较麻烦,建议用scanf格式化读入。
Code
#include<iostream> #include<algorithm> using namespace std; int n,m; const int maxn=1e6+100; int tree[maxn][3]; int cnt[maxn]; string res[maxn]; int tot=0; void insert(int x,int len,int id){ int root=0; for(int i=31;i>=0;i--){ int op=(x>>i)&1; if(!tree[root][op]) tree[root][op]=++tot; root=tree[root][op]; len--; if(len==0){ cnt[root]=id; } } } int query(int x){ int t=0; int root=0; for(int i=31;i>=0;i--){ int op=(x>>i)&1; if(!tree[root][op]){ break; } root=tree[root][op]; if(cnt[root]){ t=cnt[root]; } } return t; } int main(){ cin>>n; for(int i=1;i<=n;i++){ int a,b,c,d,len; scanf("%d.%d.%d.%d %d",&a,&b,&c,&d,&len); cin>>res[i]; if(len==0){ res[0]=res[i]; } int base=(a<<24)|(b<<16)|(c<<8)|d; insert(base,len,i); } cin>>m; for(int i=1;i<=m;i++){ int a,b,c,d,len; scanf("%d.%d.%d.%d",&a,&b,&c,&d); int base=(a<<24)|(b<<16)|(c<<8)|d; cout<<res[query(base)]<<"\n"; } }