HDU1880 (2020.3.12训练D题)

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;
			}
		}
	}
	
}
发布了16 篇原创文章 · 获赞 21 · 访问量 1330

猜你喜欢

转载自blog.csdn.net/rainbowower/article/details/104838635
今日推荐