手搓模版系列001-数值哈希/字符串哈希/字典树
http://120.78.128.11/Problem.jsp?pid=2311
Home_W的猜数字游戏
TimeLimit:10000MS MemoryLimit:128MB
64-bit integer IO format:%lld
已解决 | 点击收藏
Problem Description
Home_W有n个数字组成的数列,且后一个数字严格大于前一个(a[i+1]>a[i])
V_Dragon进行Q次猜数,每次他都猜一个x,若这个x在数列中,V_Dragon的得分加上这个数的大小(注:被猜中的数不会从数列消失)
如 :数列 1 2 3 4 5 6 V_Dragon猜5次,分别为 1 1 3 5 7那V_Dragon的得分为 1+1+3+5=10
现在请你告诉V_Dragon他的得分为多少
Input
第一行输入一个T(0<T<=100)
接下来T组测试数据
每组第一行两个数n,q(1<=n,q<=1000000)
接下来一行n个数a1,a2...an(1<=a[i]<=10^9)
再接下来一行q个数b1,b2...bq(1<=b[i]<=10^9)表示猜的数字
Output
输出Home_W的得分
SampleInput
1 6 5 1 2 3 4 5 6 1 1 3 5 7
SampleOutput
10
判断一个数出现了没。因为递增数列,可二分。这里被我那来测板子。
数值哈希
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
struct Hash_table {
static const int maxn = 1<<20;
static const int maxm = 1<<22;
static const int xor_mod = maxm-1;
int first[maxm],sign;
struct Node {
int data,next;
} edge[maxn];
Hash_table() {
clear();
}
void clear() {
sign = 1;
memset(first,0,sizeof(first));
}
int get_value(int val) {
return (val) & xor_mod;
}
bool find(int val) {
int id = get_value(val);
for(int i = first[id]; i; i = edge[i].next) {
if(edge[i].data == val) {
return 1;
}
}
return 0;
}
void insert(int val) {
if(find(val)) {
return ;
} else {
int id = get_value(val);
edge[sign].data = val;
edge[sign].next = first[id];
first[id] = sign ++;
}
}
} H;
int t,n,q,val;
int main() {
while(~scanf("%d",&t)) {
while(t--) {
H.clear();
scanf("%d %d",&n,&q);
for(int i = 1; i <= n; i ++ ) {
scanf("%d",&val);
H.insert(val);
}
LL ans = 0;
for(int i = 1; i <= q; i ++ ) {
scanf("%d",&val);
if(H.find(val)) {
ans += val;
}
}
printf("%lld\n",ans);
}
}
return 0;
}
http://120.78.128.11/Problem.jsp?pid=1239
(??`ω′?)智能手机
TimeLimit: 2000/1000 MS (Java/Others) MemoryLimit: 32768/32768 K (Java/Others)
64-bit integer IO format:%I64d
已解决 | 点击收藏
Problem Description
在大家都有手机的今天。我们必须熟悉手机上的智能英文输入法。具体地讲,数字按钮可对应于英文字母分别如下所示:
2 : a, b, c 3 : d, e, f 4 : g, h, i 5 : j, k, l 6 : m, n, o
7 : p, q, r, s 8 : t, u, v 9 : w, x, y, z
当我们想输入字符串“ming”,我们需要按下数字键 9, 4, 6, 4,然后输入法会手机字典中选择,所有符合拼音的单词。
现在,问题来了,给你N组数字键的按键顺序,以及M组字符串,根据每一组的数字键的按键顺序,可以拼凑出多少个单词、Input
第一行输入T,表示有T组测试案例,每组测试案例按照下述操作进行:
第一行输入两个整数r N (1 <= N <= 5000),和M (1 <= M <= 5000),表示有N组数字键的按键顺序和M组字符串。
接下来有N行,每一行输入不超过6位数的数字,表示一组按键顺序。
再下来有M行,每一行输入一串不超过6个字符的字符串。Output
每组测试案例,根据所给的按键顺序,在M个字符串中,统计能够形成多少个匹配的字符串、
SampleInput
1 3 4 46 64448 74 ho oight mihgt go
SampleOutput
2 2 0
把字符串m个字符串转数字,查找字符串是否存在。存的时候和位置编号一起存。答案直接加上去
字符串哈希
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5+7;
int t,n,m;
int key[] = {2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
int ans[5050];
struct Hash_table {
static const int maxn = 1<<20;
static const int maxm = 1<<22;
static const int xor_mod = maxm-1;
int first[maxm],sign;
struct Node {
int next,id;
char str[15];
} edge[maxn];
Hash_table() {
clear();
}
void clear() {
sign = 1;
memset(first,0,sizeof(first));
}
int get_value(char str[]) {
int ans = 0;
for(int i = 0; str[i]; i ++ ) {
ans = (ans + str[i]) & xor_mod;
}
return (ans) & xor_mod;
}
int find(char str[]) {
int id = get_value(str);
for(int i = first[id]; i; i = edge[i].next) {
if(!strcmp(edge[i].str,str)) {
return edge[i].id;
}
}
return 0;
}
void insert(char str[],int num) {
if(find(str)) {
return ;
} else {
int id = get_value(str);
strcpy(edge[sign].str,str);
edge[sign].id = num;
edge[sign].next = first[id];
first[id] = sign ++;
}
}
} H;
int main() {
while(~scanf("%d",&t)) {
while(t--) {
memset(ans,0,sizeof(ans));
scanf("%d %d",&n,&m);
H.clear();
for(int i = 1; i <= n; i ++ ) {
char str[10];
scanf("%s",str);
H.insert(str,i);
}
for(int i = 1; i <= m; i ++ ) {
char str[10];
scanf("%s",str);
for(int j = 0; str[j]; j ++ ) {
str[j] = key[str[j]-'a']+'0';
}
int id = H.find(str);
if(id) {
ans[id] ++;
}
}
for(int i = 1; i <= n; i ++ ) {
printf("%d\n",ans[i]);
}
}
}
return 0;
}
字典树
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5+7;
int t,n,m;
int key[] = {2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
int ans[5050];
struct Trie {
struct Trie_Node {
int cnt,id;
int Next[10];
} Tab[maxn];
int sz;
Trie() {
clear();
}
void clear() {
sz = 1;
memset(Tab,0,sizeof(Tab));
}
void insert(char str[],int id) {
int len = strlen(str);
int now = 0;
for(int i = 0; i < len; i ++ ) {
char c = str[i];
if(!Tab[now].Next[c-'0']) {
Tab[now].Next[c-'0'] = sz ++;
}
now = Tab[now].Next[c-'0'];
}
Tab[now].cnt ++;
Tab[now].id = id;
}
int match(char str[]) {
int len = strlen(str);
int now = 0;
for(int i = 0; i < len; i ++ ) {
char c = str[i];
if(!Tab[now].Next[c-'0']) {
return 0;
}
now = Tab[now].Next[c-'0'];
}
if(Tab[now].cnt) {
return Tab[now].id;
} else {
return 0;
}
}
} T;
int main() {
while(~scanf("%d",&t)) {
while(t--) {
memset(ans,0,sizeof(ans));
scanf("%d %d",&n,&m);
T.clear();
for(int i = 1; i <= n; i ++ ) {
char str[10];
scanf("%s",str);
T.insert(str,i);
}
for(int i = 1; i <= m; i ++ ) {
char str[10];
scanf("%s",str);
for(int j = 0; str[j]; j ++ ) {
str[j] = key[str[j]-'a']+'0';
}
int id = T.match(str);
if(id) {
ans[id] ++;
}
}
for(int i = 1; i <= n; i ++ ) {
printf("%d\n",ans[i]);
}
}
}
return 0;
}