Problem Description
哈利波特在魔法学校的必修课之一就是学习魔咒。据说魔法世界有100000种不同的魔咒,哈利很难全部记住,但是为了对抗强敌,他必须在危急时刻能够调用任何一个需要的魔咒,所以他需要你的帮助。
给你一部魔咒词典。当哈利听到一个魔咒时,你的程序必须告诉他那个魔咒的功能;当哈利需要某个功能但不知道该用什么魔咒时,你的程序要替他找到相应的魔咒。如果他要的魔咒不在词典中,就输出“what?”
Input
首先列出词典中不超过100000条不同的魔咒词条,每条格式为:
[魔咒] 对应功能
其中“魔咒”和“对应功能”分别为长度不超过20和80的字符串,字符串中保证不包含字符“[”和“]”,且“]”和后面的字符串之间有且仅有一个空格。词典最后一行以“@END@”结束,这一行不属于词典中的词条。
词典之后的一行包含正整数N(<=1000),随后是N个测试用例。每个测试用例占一行,或者给出“[魔咒]”,或者给出“对应功能”。
Output
每个测试用例的输出占一行,输出魔咒对应的功能,或者功能对应的魔咒。如果魔咒不在词典中,就输出“what?”
本题其实就是一个字符串和字符串对应的问题,用哈希函数+二分即可ac
题解写的很好,借鉴了一下
ac代码:
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
using namespace std;
#define mod 1000000007
#define ll long long
ll bat = 26;
ll hashh[100000];
const int maxn = 100005;
ll Qpow(ll a, ll b, ll p) //快速幂
{
ll ans = 1;
while (b > 0)
{
if (b & 1) ans = (ans * a) % p;
a = (a * a) % p;
b >>= 1;
}
return ans % p;
}
ll gethash(ll l, ll r)
{
ll ans = (hashh[r] - hashh[l - 1] * Qpow(bat, r - l + 1, mod)) % mod;
if (ans < 0) ans += mod; //可能会出现小于零的情况
return ans;
}
ll gethash(char *str)
{
int bat = 131;
int sum = 0;
int len = strlen(str);
for (int i = 0; i < len; i++)
{
sum = sum * bat + str[i]-'a';
}
return sum;
}
struct node
{
int has, i; //定义哈希值和对应的序号,便于二分查找
bool friend operator < (node a, node b)
{
return a.has < b.has;
}
}cnt1[maxn], cnt2[maxn]; //分别代表魔咒和功能
char str1[maxn][30], str2[maxn][100];
int len = 0;
int main()
{
while (scanf("%s",str1[len]) && strcmp(str1[len], "@END@"))
{
//scanf("%s",str2[len++]);
getchar();
gets(str2[len++]);//不能用scanf,读不了字符串里的空格
}
for(int i = 0; i < len; i++)
{
cnt1[i].has = gethash(str1[i]);
cnt2[i].has = gethash(str2[i]);
cnt1[i].i = cnt2[i].i = i;
} //分别计算魔咒和功能的哈希值存入cnt1和cnt2,编号i记录好便于找到
sort(cnt1, cnt1 + len);
sort(cnt2, cnt2 + len);
int n;
cin >> n;
getchar();
for (int i = 0; i < n; i++)
{
char str[105];
gets(str);
node tt;
if (str[0] == '[')
{
tt.has = gethash(str);
int pos = lower_bound(cnt1,cnt1 + len,tt) - cnt1;//记录出现第一次大等于目标值的位置
if (cnt1[pos].has == tt.has)
{
cout<<str2[cnt1[pos].i]<<endl;
}
else
{
cout<<"what?"<<endl;
}
}
else
{
tt.has = gethash(str);
int pos = lower_bound(cnt2, cnt2 + len, tt) - cnt2;
if (cnt2[pos].has == tt.has)
{
int len = strlen(str1[cnt2[pos].i]);
str1[cnt2[pos].i][len - 1] = '\0';
printf("%s\n", str1[cnt2[pos].i] + 1); //输出魔咒时记得排掉'['和']'
}
else
{
cout << "what?" << endl;
}
}
}
}