ZOJ 3826(字符串hash)

本体的意思是给了一个{ key:value , key:value  ..... }的串,且value的形式可以也是这个形式(即是递归的),那么给定一些key1.key2.key3...类似如此的键值查询,让输出对饮键下的value,(没有该键值输出Error!)

example: 

输入 :

{"hm":"Edward","stu":{"stu01":"Alice","stu02":"Bob"}}
4
"hm"
"stu"
"stu"."stu01"
"students"

输出为:

"Edward"
{"stu01":"Alice","stu02":"Bob"}
"Alice"
Error!

对于本题目,查了一下,竟然都是对每个链状字符串(把从根key到目标key的所有字符串看做一条链),由于“ : ”最多为10000个,那么意味着最终要保存的hash值也就只有10000条,用hash的话冲突的概率极低,所以大家就妥妥的过了,只不过坑了乖孩子,不敢这么玩的人可就惨了。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include <vector>
#include <queue>
#include <map>
#include <string>
using namespace std;
#define ls (rt<<1)
#define rs (ls|1)
#define fst first
#define snd second
#define lson l,mid,ls
#define rson mid+1,r,rs
#define rep(i,n) for(int i=0;i<(int)n;i++)
#define rep1(i,x,y) for(int i=x;i<=(int)y;i++)
#define clr(a, x) memset(a, x, sizeof a)
typedef long long LL;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 1010101;
const int BASE = 131;

inline int id(char c){return ((int)c)%(BASE); }
int p;
char str[N],src[N];
map<LL,pii> M;
void build(LL pre){
    while(str[p]!='}'){
        int now = pre;
        if(str[++p]=='}') return ;
        while(str[p]!=':'){
           now=now*BASE+id(str[p]);
           p++;
        }
        int st = ++p;
        if(str[p]=='{'){
           build(now*BASE+id('.'));
        }
        else {
           while(str[p+1]!=','&&str[p+1]!='}') p++;
        }
        M[now]=pii(st,p++);
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
       M.clear();
       scanf("%s",str);
       p = 0; build(0);
       int Q; scanf("%d",&Q);
       while(Q--){
           scanf("%s",src);
           int len = strlen(src),res=0;
           rep(i,len) res=res*BASE+id(src[i]);
           if(!M.count(res)) printf("Error!\n");
           else {
           pii te = M[res];
           rep1(i,te.first,te.second)  printf("%c",str[i]);
           printf("\n");
           }
       }
    }
    return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值