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";
    }
}

 

posted @ 2021-09-23 10:44  lipu123  阅读(138)  评论(0)    收藏  举报