题面
“ 吕弗·普自小从英国长大,
受到骑士精神的影响,吕弗·普的梦想便是成为一位劫富济贫的 骑士。
吕弗·普拿到了一份全国富豪的名单,不在名单上的都是穷人(贫富两极分化很严重),上面写着所有富豪的名字以及他们的总资产,
比如豪特斯·珀去年资产有 86E,吕弗·普就会准备抢来资助贫困的伯恩兄弟…… ”
现在吕弗·普做了 M 次打劫计划,每次要打劫若干个人,他想知道每次能打劫到的总资产是多少
【样例输入】
2
a 10
b 20
3
2 a b
1 b
2 a c
【样例输出】
30
20
-1
题解
暴力的做法是,用string存名字,放在map里,暴力查找,可得70pts
主要耗时间的是map内部的比较和每次比较的字符串遍历,那么把字符串哈希过后放进去不就好了,
这是笔者的第一篇哈希题解,主要目的是讲哈希的,就简单地说一下好了,
把所有都是小写字母的字符串映射为一个数,最常见的就是把它表示成一个26进制数了,60部分分的名字就可以这样表示成long long,然后超过long long了怎么办,把它取模一个自己定义的够复杂的数,于是两个字符串的映射就很难相同,但是还是有一定概率会错,于是可以把每个字符串多映射成几种版本(其实就是把字符串映射成一个小数组,一般两三个数),每个版本都相同字符串才算相同,这样映射是有很强的优越性的,具体体现在数之间的比较远远快于字符串之间的比较,等。
那这道题呢,笔者是把字符串哈希(映射)成一个三元组,第一关键字是长度,然后是字符串的26进制数分别取模(1e9+7+rand())和998344353的两个数。(因为笔者以前一个长度+一个模数被卡怕了,现在用哈希特别谨慎)
CODE
(加了freopen)
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 3000005
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define lowbit(x) ((-x) & (x))
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
const int MOD1 = 1000103007;
const int MOD2 = 998344353;
int n,m,i,j,s,o,k;
map<int,map<int,int> > b;// Wi + 1
struct it{
int le;
int h1;
it(){le = h1 = 0;}
};
it operator * (it a,int b) {
a.h1 = a.h1 *1ll* b % MOD1;
return a;
}
it operator + (it a,int b) {
(a.h1 += b) %= MOD1;
return a;
}
it gethash(char *s,int n) {
it as;as.le = n;as.h1 = 0;
for(int i = 1;i <= n;i ++) {
as = (as * 26) + (s[i]-'a');
}
return as;
}
int main() {
freopen("liverpool.in","r",stdin);
freopen("liverpool.out","w",stdout);
n = read();
for(int i = 1;i <= n;i ++) {
it as;as.le = 0;as.h1 = 0;
char ss = getchar();
while(ss < 'a' || ss > 'z') ss = getchar();
while(ss >= 'a' && ss <= 'z') {
as = (as * 26) + (ss - 'a');
as.le ++;
ss = getchar();
}
k = read();
b[as.le][as.h1] = k+1;
}
m = read();
for(int i = 1;i <= m;i ++) {
k = read();
bool flag = 0;
LL ans = 0;
while(k --) {
it as;as.le = 0;as.h1 = 0;
char ss = getchar();
while(ss < 'a' || ss > 'z') ss = getchar();
while(ss >= 'a' && ss <= 'z') {
as = (as * 26) + (ss - 'a');
as.le ++;
ss = getchar();
}
if(flag) continue;
int ass;
if((ass = b[as.le][as.h1]) <= 0) flag = 1;
else ans += ass-1;
}
if(flag) printf("-1\n");
else printf("%lld\n",ans);
}
return 0;
}