哈希表与离散化(题目)

2024-06-05 04:28
文章标签 题目 哈希 离散 表与

本文主要是介绍哈希表与离散化(题目),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

A. 子串判重

题目描述:

给定一个含有 26 个小写英文字母的字符串。有 m 次询问,每次给出 2 个区间,请问这两个区间里的子字符串是否一样?

输入:

第一行输入一个字符串 S 。

第二行一个数字 m,表示 m 次询问。

接下来 m 行,每行四个数字 l1​,r1​,l2​,r2​ ,分别表示此次询问的两个区间,注意字符串的位置从 1 开始编号。

数据范围:

1≤length(S),m,l1​,r1​,l2​,r2​≤1000000。

输出:

对于每次询问,输出一行表示结果。

如果两个子串完全一样,输出 Yes,否则输出 No(注意大小写)。

样例:

输入:

aabbaabb

3

1 3 5 7

1 3 6 8

1 2 1 2

输出:

Yes

No

Yes

代码如下:​​​​​​

字符串哈希问题,注意本题数据量较大,因此不要循环字符串时求字符串长度,如果在循环中求,循环一次,求解一次,效率很低。

#include <bits/stdc++.h>
using namespace std;const int N = 1e6 +10,P = 131;
typedef unsigned long long ULL;
int m;
char s[N];
ULL h[N],p[N];//求子串的哈希
ULL fun(int l,int r){return h[r] - h[l-1] * p[r-l+1];
} int main(){scanf("%s%d",s+1,&m);//下标从1开始取p[0] = 1;//计算次数过多,不用每次循环都求一次长度int len = strlen(s+1); //预处理前缀和,以及p^n for(int i = 1;i <= len;i++){p[i] = p[i-1] * P;h[i] = h[i-1] * P + s[i]-'a'+1;} int l1,r1,l2,r2;while(m--){scanf("%d%d%d%d",&l1,&r1,&l2,&r2);if(fun(l1,r1)==fun(l2,r2)) printf("Yes\n");else printf("No\n");}return 0;
}


B. 前缀和后缀

题目描述:

给定若干由小写字母组成的字符串(这些字符串总长 ≤4×10^{5}),在每个字符串中求出所有既是前缀又是后缀的子串长度。

例如:ababcababababcabab,既是前缀又是后缀的:

ab,abab,ababcabab,ababcababababcabab 。

输入:

输入若干行,每行一个字符串。

输出:

对于每个字符串,输出一行,包含若干个递增的整数,表示所有既是前缀又是后缀的子串长度。

样例:

输入:

ababcababababcabab
aaaaa

输出:

2 4 9 18
1 2 3 4 5

代码如下

#include <bits/stdc++.h>
using namespace std;const int N = 4e5 + 10;
typedef unsigned long long ULL;
ULL h[N],p[N],P = 131;
char s[N];ULL get(int l,int r){return h[r] - h[l-1] * p[r-l+1];
}int main()
{while(scanf("%s",s+1)!=EOF){p[0] = 1;//预处理字符串前缀哈希值 和 p的次方for(int i = 1; s[i]; i++){p[i] = p[i-1] * P;h[i] = h[i-1] * P + (s[i]-'a'+1);}//计算所有可能的长度int len = strlen(s+1);for(int i = 1;i <= len;i++){if(get(1,i)==get(len-i+1,len)) printf("%d ",i);}printf("\n");}return 0;
}

C. 最多子串重复次数

题目描述:

给定若干个长度 ≤106 的字符串,询问每个字符串最多是由多少个相同的子字符串重复连接而成的。如:ababab 则最多有 3 个 ab 连接而成。

输入:

输入若干行(所有行的字符串的长度之和≤107),每行有一个字符串,字符串仅含英语小写字母。特别的,字符串可能为 . 即一个半角句号,此时输入结束。

输出:

对于每行输入,输出一个整数,代表计算的结果。

样例:

输入:

abcd
aaaa
ababab
.

输出:

1
4
3

代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=1e6+10,P=131;
ull h[N],p[N];
char s[N];
int m,len;
ull get(int l,int r){return h[r]-h[l-1]*p[r-l+1];
}
bool check(ull hh,int k){for(int i=k+1;i<=len;i+=k){if(get(i,i+k-1)!=hh) return 0;}return 1;
}
int main(){for(int i;;i++){scanf("%s",s+1);if(s[1]=='.') break;p[0]=1;len=strlen(s+1);for(int i=1;i<=len;i++){p[i]=p[i-1]*P;h[i]=h[i-1]*P+(s[i]-'a'+1);}for(int i=1;i<=len;i++){if(len%i==0){if(check(h[i],i)){printf("%d\n",len/i);break;}}}} return 0;
}

D. 书号管理

题目描述:

图书管理是一件十分繁杂的工作,在一个图书馆中每天都会有许多新书加入。为了更方便的管理图书(以便于帮助想要借书的客人快速查找他们是否有他们所需要的书),我们需要设计一个图书查找系统。

该系统需要支持 2 种操作:

add(x) 表示新加入一本书号为 x 的图书。

find(x) 表示查询是否存在一本书号为 x 的图书。

输入:

第一行包括一个正整数 n,表示操作数。 以下 n 行,每行给出 2 种操作中的某一个指令条,指令格式为:

add x
find x

在书号 x 与指令(add,find)之间有一个隔开,我们保证所有书号都是一个值在 [−109≤x≤109] 之间的整数。

本题 n≤106 。

输出:

对于每个 find(x) 指令,我们必须对应的输出一行 yes 或 no,表示当前所查询的书是否存在于图书馆内。

注意:一开始时图书馆内是没有一本图书的,本题允许加入到图书馆的书号 x 出现重复。

样例:

输入:

8
add 3
add 100006
add 6
find 6
add 100009
find 9
add -100000
find 3

输出:

yes
no
yes

代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=1e6+3;
ull h[N],e[N],ne[N],idx;
int n;
void insert(int x){int v=(x%N+N)%N;idx++;e[idx]=x;ne[idx]=h[v];h[v]=idx;
}
bool query(int x){int v=(x%N+N)%N;for(int i=h[v];i!=0;i=ne[i]){if(e[i]==x) return 1;}return 0;
}
int main(){scanf("%d",&n);char order[10];int x;while(n--){scanf("%s%d",order,&x);if(order[0]=='a') insert(x);else{if(query(x)) printf("yes\n");else printf("no\n");}}return 0;
}

E. 图书管理

题目描述:

图书管理是一件十分繁杂的工作,在一个图书馆中每天都会有许多新书加入。为了更方便的管理图书(以便于帮助想要借书的客人快速查找他们是否有他们所需要的书),我们需要设计一个图书查找系统。

该系统需要支持 2 种操作:

add(s) 表示新加入一本书名为 s 的图书。

find(s) 表示查询是否存在一本书名为 s 的图书。

输入:

第一行包括一个正整数 n,表示操作数。

以下 n 行,每行给出 22 种操作中的某一个指令条,指令格式为:

add s
find s

在书名 s 与指令(add,find)之间有一个空格隔开,我们保证所有书名的长度都不超过 200 。

可以假设读入数据是准确无误的。

本题 n≤30000 。

输出:

对于每个 ����(�)find(s) 指令,我们必须对应的输出一行 yes 或 no,表示当前所查询的书是否存在于图书馆内。

注意:一开始时图书馆内是没有一本图书的。并且,对于相同字母不同大小写的书名,我们认为它们是不同的。

样例:

输入:

4
add Inside C#
find Effective Java
add Effective Java
find Effective Java

输出:

no
yes

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10,M=1e4+10;
int a[N],b[N],c[M];
int n;
int main(){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&a[i]);b[i]=a[i];}sort(b+1,b+n+1);int k=unique(b+1,b+n+1)-b-1;int x;for(int i=1;i<=n;i++){x=lower_bound(b+1,b+k+1,a[i])-b;c[x]++;}for(int i=1;i<=k;i++){printf("%d %d\n",b[i],c[i]);}return 0;
}

G. 自动灌溉

题目描述:

农场的有一个用于科学研究的大棚,大棚内有一条笔直的直线,直线的每个整数位置上都种植了一株科研植物,整数位置的范围为 [0,109]。

大棚内设有一个自动灌溉机,会根据各植物检测到的特征数据,对特定位置的植物进行灌溉 。

现从计算机中调取了某一天 N 次灌溉记录。第 i 条灌溉记录有两个数据 Pi​ 和 Xi​,代表为位于 Pi​ 位置的植物,灌溉了 Xi​ 毫升的水。

针对当天的灌溉记录有 M 次询问,第 j 条询问需要计算一个区间 [Lj​,Rj​] 当天的总灌溉量。

请编程计算出 M 次询问,每次的询问结果。

输入:

第 1 行读入 2 个整数 N 和 M;

接下来 N 行,每行读入 2 个整数 P 和 X;

接下来 M 行,每行读入 2 个整数 L 和 R;

输出:

输出 M 行,每行一个整数,代表每次询问的结果。

样例:

输入:

3 4
2 1
8 2
5 3
1 3
2 5
3 8
2 8

输出:

1
4
5
6

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int p[N],x[N],l[N],r[N];
int a[N*3],c[N*3],k=0;
int n,m;
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d%d",&p[i],&x[i]);a[++k]=p[i];}for(int i=1;i<=m;i++){scanf("%d%d",&l[i],&r[i]);a[++k]=l[i];a[++k]=r[i];}sort(a+1,a+k+1);k=unique(a+1,a+k+1)-a-1;for(int i=1;i<=n;i++){p[i]=lower_bound(a+1,a+k+1,p[i])-a;c[p[i]]+=x[i];}for(int i=1;i<=k;i++){c[i]+=c[i-1];}for(int i=1;i<=m;i++){l[i]=lower_bound(a+1,a+k+1,l[i])-a;r[i]=lower_bound(a+1,a+k+1,r[i])-a;printf("%d\n",c[r[i]]-c[l[i]-1]);}return 0;
}

H. 程序自动分析

题目描述:

在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。

考虑一个约束满足问题的简化版本:假设 x1​,x2​,x3​,⋯ 代表程序中出现的变量,给定 n 个形如 xi​=xj​ 或 xi​≠xj​ 的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足。例如,一个问题中的约束条件为:x1​=x2​,x2​=x3​,x3​=x4​,x4≠x1​,这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。

现在给出一些约束满足问题,请分别对它们进行判定。

输入:

输入的第一行包含一个正整数 t,表示需要判定的问题个数。注意这些问题之间是相互独立的。

对于每个问题,包含若干行:

第一行包含一个正整数 n,表示该问题中需要被满足的约束条件个数。接下来 n 行,每行包括三个整数 i,j,e,描述一个相等/不等的约束条件,相邻整数之间用单个空格隔开。若 e=1,则该约束条件为 xi​=xj​。若e=0,则该约束条件为 xi​≠xj​。

输出:

输出包括 t 行。

输出文件的第 k 行输出一个字符串 YES 或者 NO(字母全部大写),YES 表示输入中的第 k 个问题判定为可以被满足,NO 表示不可被满足。

样例:

输入:

2
2
1 2 1
1 2 0
2
1 2 1
2 1 1

输出:

NO
YES

输入:

2
3
1 2 1
2 3 1
3 1 1
4
1 2 1
2 3 1
3 4 1
1 4 0

输出:

YES
NO

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
struct node{int x,y,e;
}a[N];
int b[N*2],fa[N*2],k;
int n,t;
bool f;
bool cmp(node n1,node n2){return n1.e>n2.e;
}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){int rx=find(x);int ry=find(y);if(rx!=ry){fa[rx]=ry;}
}
int main(){scanf("%d",&t);while(t--){scanf("%d",&n);for(int i=1;i<=n*2;i++){fa[i]=i;}k=0;for(int i=1;i<=n;i++){scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].e);b[++k]=a[i].x;b[++k]=a[i].y;}sort(b+1,b+k+1);k=unique(b+1,b+k+1)-b-1;sort(a+1,a+n+1,cmp);f=1;for(int i=1;i<=n;i++){a[i].x=lower_bound(b+1,b+k+1,a[i].x)-b;a[i].y=lower_bound(b+1,b+k+1,a[i].y)-b;if(a[i].e==1){merge(a[i].x,a[i].y);}else{if(find(a[i].x)==find(a[i].y)){f=0;break;}}}if(f) puts("YES");else puts("NO");}return 0;
}

这篇关于哈希表与离散化(题目)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1032066

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

题目1254:N皇后问题

题目1254:N皇后问题 时间限制:1 秒 内存限制:128 兆 特殊判题:否 题目描述: N皇后问题,即在N*N的方格棋盘内放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在同一斜线上。因为皇后可以直走,横走和斜走如下图)。 你的任务是,对于给定的N,求出有多少种合法的放置方法。输出N皇后问题所有不同的摆放情况个数。 输入

题目1380:lucky number

题目1380:lucky number 时间限制:3 秒 内存限制:3 兆 特殊判题:否 提交:2839 解决:300 题目描述: 每个人有自己的lucky number,小A也一样。不过他的lucky number定义不一样。他认为一个序列中某些数出现的次数为n的话,都是他的lucky number。但是,现在这个序列很大,他无法快速找到所有lucky number。既然

哈希表的底层实现(1)---C++版

目录 哈希表的基本原理 哈希表的优点 哈希表的缺点 应用场景 闭散列法 开散列法 开放定值法Open Addressing——线性探测的模拟实现 超大重点部分评析 链地址法Separate Chaining——哈希桶的模拟实现 哈希表(Hash Table)是一种数据结构,它通过将键(Key)映射到值(Value)的方式来实现快速的数据存储与查找。哈希表的核心概念是哈希

哈希表的封装和位图

文章目录 2 封装2.1 基础框架2.2 迭代器(1)2.3 迭代器(2) 3. 位图3.1 问题引入3.2 左移和右移?3.3 位图的实现3.4 位图的题目3.5 位图的应用 2 封装 2.1 基础框架 文章 有了前面map和set封装的经验,容易写出下面的代码 // UnorderedSet.h#pragma once#include "HashTable.h"

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

PHP: 深入了解一致性哈希

前言 随着memcache、redis以及其它一些内存K/V数据库的流行,一致性哈希也越来越被开发者所了解。因为这些内存K/V数据库大多不提供分布式支持(本文以redis为例),所以如果要提供多台redis server来提供服务的话,就需要解决如何将数据分散到redis server,并且在增减redis server时如何最大化的不令数据重新分布,这将是本文讨论的范畴。 取模算法 取模运

哈希表题总结

哈希表题总结 hot100两数之和字母异位词分组最长连续序列 hot100 两数之和 题目链接: 1.两数之和 代码: class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer,Integer> map = new HashMap<>();int n = nums.length;for

码蹄集部分题目(2024OJ赛9.4-9.8;线段树+树状数组)

1🐋🐋配对最小值(王者;树状数组) 时间限制:1秒 占用内存:64M 🐟题目思路 MT3065 配对最小值_哔哩哔哩_bilibili 🐟代码 #include<bits/stdc++.h> using namespace std;const int N=1e5+7;int a[N],b[N],c[N],n,q;struct QUERY{int l,r,id;}que