什么是HASH表
当我们要查询几个数组里的元素时,往往用到朴素算法 O ( n ) O(n) O(n)会超时,而二分虽然时间复杂度为 O ( l o g n ) O(log_n) O(logn)又只能在数组有序的情况下使用,所以在这种时候,我们就需要用到hash表
Hash,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
三、冲突
两个不同的关键字具有相同的存储位置。(多个关键字通过hash函数得到的地址是同一个地址)
通过上面的介绍,我们可以发现hash表可以把分散的数据统计到一个哈希表里面,以减少空间和时间的损耗,思想就是映射,难点在于想出hash函数和解决冲突的方法
今天 l i f a n lifan lifan老师告诉我们hash的题十有八九与字符串有关,而字符串有十有八九与二分有关,所以关键要掌握好字符串的处理和怎样二分的思想
例题
A. Crazy Search
题目描述
给出一个字符串,共包含NC种字符(种数不超过ASCII码),求这个字符串中长度为N的子串(不包含重复)的数量。题目中子串个数不超过16000000个。输入第一行包含两个数字,分别为N,NC。第二行输入字符串。输出符合要求的子串个数。
输入格式
第一行2个数n和nc (n<=5, nc<=40) 第二行一个长度不超过16000000的字符串
输出格式
不同子串个数
样例
样例输入
3 4
daababac
样例输出
5
这道题可以用到将每个字符转化为m进制数的思想,这样如果顺序不同但字符相同,也会因为值的不同而不被记录下来
在乘的时候最好要%一个大些的质数,如31,131,1313,1331,99991,这样不至于让hash地址过大
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int INF=16000005;
char c[INF];
bool hash[INF];
int id[260];
int main()
{
int n,m,cnt=0,ans=0;
scanf("%d%d",&n,&m);
scanf("%s",c+