nefu暑假集训4 哈希 个人模板+例题汇总

2024-09-01 11:04

本文主要是介绍nefu暑假集训4 哈希 个人模板+例题汇总,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

  什么是哈希?哈希其实是所有字符串操作中,最简单的操作了(哈希的过程,其实可以看作对一个串的单向加密过程,并且需要保证所加的密不能高概率重复(就像不能让隔壁老王轻易地用它家的钥匙打开你家门一样qwq),通过这种方式来替代一些很费时间的操作。 比如,最常见的,当然就是通过哈希数组来判断几个串是否相同(洛谷P3370)。此处的操作呢,很简单,就是对于每个串,我们通过一个固定的转换方式,将相同的串使其的“密”一定相同,不同的串 尽量 不同。 此处有人指出:那难道不能先比对字符串长度,然后比对ASCLL码之和吗?事实上显然是不行的(比如ab和ba,并不是同一个串,但是如是做却会让其认为是qwq)。这种情况就叫做hash冲突,并且在如此的单向加密哈希中,hash冲突的情况在所难免(bzoj就有这种让你给出一组样例,使得一段哈希代码冲突的题,读者可以尝试尝试)

下面我给出这个暑假训练时写过的hash的题。

正文:

链接:字符串哈希及kmp专题 - Virtual Judge (vjudge.net)

模板:

//预处理
pow1[0] = 1;
for (int i = 1; i <= n; i++)
pow1[i] = pow1[i - 1] * Base1 % mod;
for (int i = 1; i <= n; i++)
{
ha1[i] = (ha1[i - 1] * Base1 + s[i]) % mod;
}
//查询
long long get_hash(int l, int r)
{
long long res1 = ((ha1[r] - ha1[l - 1] * pow1[r - l + 1] % mod) + mod) %
mod;
return res1;
}

习题:

A - 字符串哈希:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
ull base=131;
ull a[10005];
char s[10005];
int n;
ull mod=1e9+7;
ull gethash(char s[]){int len=strlen(s);ull ans=0;for(int i=0;i<len;i++){ans=(ans*base+(ull)s[i])%mod;}return ans;
}
int main(){int ans=1;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",s);a[i]=gethash(s);}sort(a+1,a+n+1);for(int i=1;i<n;i++){if(a[i]!=a[i+1])ans++;}cout<<ans<<endl;return 0;
}

哈希的模板题。

B - Barn Echoes G:

#include<bits/stdc++.h>
using namespace std;
int main(){	string a,b;cin>>a>>b;int n=min(a.size(),b.size());int i,j;for(i=n;i>=1;i--){if(a.substr(0,i)==b.substr(b.size()-i,i))break;}	for(j=n;j>=1;j--){if(b.substr(0,j)==a.substr(a.size()-j,j))break;	}cout<<max(i,j)<<endl; return 0;
} 

这题我没用hash(懒),不过hash的思路还挺简单的,就是第一个字符串的前缀的区间哈希值和第二个字符串的后缀的区间哈希值或第二个字符串的前缀的区间哈希值和第一个字符串的后缀的区间哈希值比较一下,取最大值就完了。我这边直接用substr其实意思是一样的。

C - 单词背诵:​​​​​​​

#include<bits/stdc++.h>
using namespace std;
map<string,int> mp;
map<string,bool> f;
string s[100005];
int main(){int n,m;cin>>n;for(int i=1;i<=n;i++){string x;cin>>x;f[x]=true;}cin>>m;int l=1,ans,res;for(int i=1;i<=m;i++){cin>>s[i];if(f[s[i]])mp[s[i]]++;if(mp[s[i]]==1)ans++,res=i-l+1;while(l<=i){if(!f[s[l]]){l++;continue;}if(mp[s[l]]>=2){mp[s[l]]--,l++;continue;}break;}res=min(res,i-l+1);}cout<<ans<<endl;cout<<res<<endl;return 0;
}

这题我也没用hash,直接用map来搞定映射关系了,想要用hash的直接用我第一题的hash写进去代替map中的string就行了。

D - A-B 数对:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
long long a[N];
map<int,int> mp;
int main(){long long n,m;long long ans=0;cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];mp[a[i]]++;}for(int i=1;i<=n;i++){ans+=mp[a[i]+m];	}cout<<ans<<endl;return 0;
}

这也算hash吗,map直接秒了。

E - 密文搜索:​​​​​​​

#include <bits/stdc++.h>
using namespace std;
#define int unsigned long long
int base=131;
int t[128],a[200001];
int change(){int cnt=1;for(int i='a';i<='z';i++)cnt=cnt*base+t[i];return cnt;
}
signed main()
{int len,n,ans=0;string s,s1;cin>>s>>n;len=s.size();for(int i=0;i<=len-8;i++){memset(t,0,sizeof t);for(int j=i;j<i+8;j++)t[s[j]]++;a[i]=change();}memset(t,0,sizeof t);while(n--){memset(t,0,sizeof t);cin>>s1;for(int j=0;j<8;j++)t[s1[j]]++;int b=change();for(int i=0;i<=len-8;i++)if(b==a[i]) ans++;}cout<<ans<<endl;
}

由于密码可能是被打乱的,所以我们需要规定一种hash可以直接找到一个合理的映射规则且不会产生冲突,我们可以根据字符序来规定hash的进制,这样就完美解决了这个问题。

I - 不重复数字:​​​​​​​

#include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
inline int read(){char c=getchar();int x=0,f=1;for(;!isdigit(c);c=getchar())if(c=='-')f=-1;for(;isdigit(c);c=getchar())x=x*10+c-48;return x*f;
}
int T,n,x;
unordered_map<int,bool>s;
void work()
{s.clear();n=read();For(i,1,n){x=read();if(!s[x]){printf("%d ",x);s[x]=1;}}puts("");
}
int main(){T=read();while(T--)work();return 0;
}

这题更是没什么好说的了,写法很多。

后记:

  要开学了,新学期新气象,继续努力吧!

这篇关于nefu暑假集训4 哈希 个人模板+例题汇总的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

哈希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

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

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

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al

最大流、 最小费用最大流终极版模板

最大流  const int inf = 1000000000 ;const int maxn = 20000 , maxm = 500000 ;struct Edge{int v , f ,next ;Edge(){}Edge(int _v , int _f , int _next):v(_v) ,f(_f),next(_next){}};int sourse , mee

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

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