【Week15作业 A】ZJM与霍格沃兹【字符串哈希】

题意:

ZJM 为了准备霍格沃兹的期末考试,决心背魔咒词典,一举拿下咒语翻译题。
题库格式:[魔咒] 对应功能。
背完题库后,ZJM 开始刷题,现共有 N 道题,每道题给出一个字符串,可能是 [魔咒],也可能是对应功能。
ZJM 需要识别这个题目给出的是 [魔咒] 还是对应功能,并写出转换的结果,如果在魔咒词典里找不到,输出 “what?”。

首先列出魔咒词典中不超过100000条不同的咒语,每条格式为:
[魔咒] 对应功能。
其中“魔咒”和“对应功能”分别为长度不超过20和80的字符串,字符串中保证不包含字符“[”和“]”,且“]”和后面的字符串之间有且仅有一个空格。魔咒词典最后一行以“@END@”结束,这一行不属于词典中的词条。
词典之后的一行包含正整数N(<=1000),随后是N个测试用例。每个测试用例占一行,或者给出“[魔咒]”,或者给出“对应功能”。

每个测试用例的输出占一行,输出魔咒对应的功能,或者功能对应的魔咒。如果在词典中查不到,就输出“what?”


思路:

这道题卡内存,需要用到字符串哈希算法。用unsigned long long来存储字符串的哈希值,从字符串最后一位到第一位,每一个字符的ACSII值都乘以seed=7的i次方,i从1开始依次增一。这里采用了unsigned long long自然溢出,没有使用mod取模。
读入题库,string s1[]存储功能,string s2[]存储魔咒。然后建立两个map<unsigned long long,int>mp1,mp2,设魔咒哈希值为hash1,功能为hash2,则mp1[hash1]=index,s1[index]=功能;mp2[hash2]=index,s2[index]=魔咒。
查询时先判断是魔咒还是功能,然后在对应的map中查询即可。


总结:

一道字符串哈希题目,设计到了字符串的读入、处理等。读入时字符串内可能有空格,所以要用getline(cin,str)读入,还要记得getchar()吃回车或空格;string的删除是str.erase(index,len),从str[index]开始删除len个字符(包括str[index])。还要注意函数名不能命名为hash,与std::hash冲突,
相同的代码G++会MLE,C++就能A,很是神奇。


代码:

#include <iostream>
#include <map>
#include <cmath>
#include <string>
using namespace std;
#define ull unsigned long long
string s1[100001],s2[100001];
int n;
map<ull,int> mp1,mp2;
const ull seed=7;
ull bkdrHash(string s)
{
	ull ret=0,seed1=seed;
	for(int i=s.size()-1;i>=0;i--)
	{
		ret+=(ull)s[i]*seed1;
		seed1=seed1*seed;
	}
	return ret;
}
int main()
{
	int index=1;
	string str1,str2;
	while(cin>>str1)
	{
		if(str1=="@END@")
			break;
		getchar();	//吃空格 
		getline(cin,str2);
		str1.erase(0,1);
		int len=str1.size();
		str1.erase(len-1,1);
		s1[index]=str2,s2[index]=str1;
		ull hash1=bkdrHash(str1),hash2=bkdrHash(str2);
		mp1[hash1]=index,mp2[hash2]=index; 
		index++;
	}
	cin>>n;
	getchar();	//吃回车 
	while(n--)
	{
		string str3;
		getline(cin,str3);
		if(str3[0]=='[')
		{
			str3.erase(0,1),str3.erase(str3.size()-1,1);
			map<ull,int>::iterator iter=mp1.begin();
			iter=mp1.find(bkdrHash(str3));
			if(iter!=mp1.end())
				cout<<s1[iter->second]<<endl;
			else
				cout<<"what?"<<endl;
		}
		else
		{
			map<ull,int>::iterator iter=mp2.begin();
			iter=mp2.find(bkdrHash(str3));
			if(iter!=mp2.end())
				cout<<s2[iter->second]<<endl;
			else
				cout<<"what?"<<endl; 
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值