HDU 1880 魔咒词典 (字符串hash)

<题目链接>

题目大意:

就是每个字符串有一个配套的对应字符串,询问的时候,无论输出其中的哪一个字符串,输出另一个,如果不存在这个字符串,直接输出"what?"。

解题分析:      转载于 >>> 
本题很明显要用字符串hash,数据量比较大,如果直接用map,会Mle。所以我们用hash表来处理,下面采用了一个比较优秀的hash算法-BKDR进行处理。

#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
const int MAXN = 2e6 + 100;
const int MOD = 1e6 + 7;
const int BASE = 131;
 
struct Node{
    char s[100];
    Node* next;
}Hashpos[MAXN], *head[MOD], *now;

//BKDRHash算法是字符串hash算法。是一种比较优秀的hash算法
int Get_Id(char *s){       //得到字符串hash后的hash值
    int Hash = 0;
    int len = strlen(s);
    for(int i = 0 ; i < len ; i++)
        Hash = (Hash * BASE % MOD + s[i]) % MOD ;
    return Hash;
}
void BKDRHashpos(char *s){
    int code = Get_Id(s);  
    Node* p = head[code];//取的是地址(以该code为头标志的最后一个数的地址)
    while(p){         //如果没有到达头标志一直往上
        if(!strcmp(p->s, s))    //如果hash地址相同的链表上有这个元素,直接返回
            return;
        else p = p->next;       //如果没有这个元素,就一直向后查找,直至放在链表的尾部
    }
    strcpy(now->s, s);       //将这个元素插入当前位置(最后一个位置)
    now->next = head[code];  //记录这个数上一个的地址,就是与链式前向星的作用类似
    head[code] = now++;      //更新这个code所对应的最后一个数的地址
}
int find(char *s){       
    int code = Get_Id(s);
    Node* p = head[code];
    while(p){     
        if(!strcmp(p->s, s))return p-Hashpos;    //p为当前串在哈希表上的地址,Hashpos是初始地址
        else p = p->next;
    }
    return -1;
}
int main(){
    now = Hashpos;    
    char str[100];
    while(~scanf("%s", str)){
        if(!strcmp(str,"@END@"))break;
        getchar();
        BKDRHashpos(str);     
        gets(str);BKDRHashpos(str);
    }
    int q;scanf("%d",&q);getchar();
    while(q--){
        gets(str);
        int id = find(str);
        if(id==-1) puts("what?");
        else{
            char *node = Hashpos[id^1].s;     //因为是从0开始 两两 存储,所以这里直接取异或
            if(node[0]=='['){
                for(int i=1;node[i]!=']';i++)
                    printf("%c",node[i]);
                puts("");
            }
            else puts(node);
        }
    }
}

 

转载于:https://www.cnblogs.com/00isok/p/10792513.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值