array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 哈希,hash - 爱码网

Hash,一般翻译做散列、杂凑,或音译为哈希。————摘自百度百科
先来看个题:给你一坨一些键值集<key,value>,\(key\)的范围是\([1,10^{10}]\),每次询问\(x\),回答\(key=x\)\(value\)这种一看就知道暴力不行……于是,有些同学会说:我会用map!但map的查询是 \(O(logn)\)的 QwQ。那么哈希可以怎么做呢?我们可以让\(hash[f(key)]=value\),其中\(f()\)函数被称为哈希函数。至于\(f()\)函数怎么写……想怎么写就怎么写!没错,你想怎么写就怎么写。一般有这么几种方法:

  1. 直接定值法:让\(F(key)=key\)。读者:那不和一般的一样嘛!要你何用?咳咳,总要从最基础的开始嘛……好了,这个方法就此结束。
  2. 折叠法:将关键字分成几部分,取这几部分的和的前几位为哈希地址。例如ISBN码(对就是那道入门题),以0-442-20586-4为例,可以得到其哈希地址是:\(hash = 0442 + 2058 + 64 = 2564\)诶?之前不是说前几位吗?因为这里没有进位啊……如果得到结果是\(10934\),那么其哈希地址就是\(0934\)
  3. 取余数法:这是\(OI\)中最最常用的,就是对其求余为哈希地址,如\(4325\),模\(233333\)后得\(4325\),那么她的哈希地址就是\(4325\)

那么现在上面那个问题就好解决了,只要用取余数法求得\(key\)的哈希地址就可以大大压缩空间了!
但是,你不要高兴太早!相信有许多人已经看出来了,哈希的缺点很明显,就是容易出现不同的元素有同一个哈希地址的情况,我们一般称其为:哈希冲突。那么有什么方法能解决哈希冲突呢?有许多方法:

  1. 线性探测再散列:如果多个数有同一个哈希地址,如:0 0 0 34 6 44 0 0注:0表示没有元素。然后又有一个元素\(8\),得到其哈希地址也是4(即34所在的位置),那么我们就往后挪一挪:大哥你先来的,我到后面去。于是来到了6的位置——也被占了,那么再往后移……最后到了7(即44后面那个)。然后查询时只要依次往后找就可以了。
  2. 多重哈希:个人比较喜欢叫双模数,就是进行多次哈希,当然,每次的模数都不一样。如果两次哈希的地址都对应,我才认为是同一个。一般情况下双模数就足够了,所以我喜欢叫双模数。要是有三模数,那基本不会冲突了。
  3. 链地址法:还记得链式前向星吗?(不记得!那还不滚回去学)链式前向星就是把其后面一个一个地链起来,这个也一样,如果哈希地址相同,就链起来。于是乎,我们又想:那开个\(vector\)岂不是又方便又可以解决哈希冲突?没错,我也喜欢用\(vector\)。这两种你用哪一种都没关系,不过还是先提醒一下:\(vector\)有可能会爆哦!这也是为什么大家用链式前向星而不用\(vector\)的原因!(所以我也要开始习惯用链地址法了)。
  4. 建立一个公共溢出区:这个方法我不会!(不会还理直气壮……)所以这里不讲,而且这个方法最后得到的模数不是一个质数,而且其因数很多,是2的次幂,所以……出题人卡你是很容易的!

解决哈希冲突的方法一般就是这些啦!还有个问题,上面提到模数要是质数,为什么呢?原因很简单,根据质数的特性,质数每一个位置都能很好的利用起来,而合数不可以。而且这个质数要大一点(废话,你来个19,玩个鬼哦)。
好,讲完了基础的,来看一看例题:
P3370 【模板】字符串哈希
噫,刚刚只说了整数哈希啊!没关系,记得ASCII码吗?我们可以通过ASCII码,将其转成一个\(base\)进制数,当然,是模过的。然后再用链地址法,对同一哈希值的字符串进行遍历,如果都不相同,加入并更新答案。
具体代码实现:

#include<cstdio>
#include<string>
#include<vector>
#include<iostream>
#define mod 23333
#define base 298
#define rg register
using namespace std;
int n,ans;
string s;
vector<string>v[mod+5];
void insert()
{
	int hash=1;//记录哈希值,由于后面要乘所以初值是1
	for(rg int i=0;i<s.length();i++)
		hash=(1ll*hash*base+s[i])%mod;//1ll就是(long long)1,乘一个1ll,可以保证不爆精度(当然你爆long long或高精度我也没办法)
	string t=s;//暂存一下
	for(rg int i=0;i<v[hash].size();i++)
		if(v[hash][i]==t) return ;//判断,如果有相同的就退出
	v[hash].push_back(t);//加入新的字符串
	ans++;//更新答案
	return ;
}
int main()
{
	scanf("%d",&n);
	for(rg int i=1;i<=n;i++)
	{
		cin>>s;
		insert();
	}
	printf("%d",ans);
	return 0;
}

哦对了,一般233333(2后面跟一堆3)、100007(1和7中间隔一堆0)、1000009(1和9中间隔一堆0)都是质数。

就讲这么多吧,之后就要靠大家自己实现了!重点还是在多刷题啊!

相关文章:

  • 2018-06-11
  • 2018-03-03
  • 2018-02-28
  • 2018-09-19
  • 2021-08-13
  • 2018-11-03
  • 2020-11-12
  • 2020-02-02
猜你喜欢
  • 2021-12-28
  • 2020-06-30
  • 2019-08-05
  • 2018-10-16
  • 2021-02-20
  • 2019-05-19
  • 2021-08-16
  • 2019-01-02
相关资源
相似解决方案