浅谈字符串哈希 By cellur925
前言
蒟蒻最近在复习字符串算法...但正如之前所说,我OI太菜被关起来了,本蒟蒻只能从最简单的哈希入手了TAT。而别的dalao都在学习AC自动机/后缀数组等高到不知哪里去的算法qwq。
基本思想
映射。把一个任意长度的字符串映射为一个非负整数,要求冲突概率几乎为0。方法是把字符串看成$p$进制数,通常取$p$为131或13331,当然还有特殊情况,如[CTSC2014]企鹅QQ这道题,之后会解释这种情况。
基本操作
*****************采用unsigned long long存储哈希值和131的幂次***********************
一般情况下,我们都是预处理出字符串前缀子串的哈希值,如下。复杂度是$O(n)$的。
for(int i=;i<=len;i++)
f[i]=f[i-]*+ch[i];
//ch[]是字符数组
当然也可以边用边求啦qwq,主要用于带修改的情况,如[USACO15FEB]审查(黄金)Censoring (Gold),就不能预处理出来,因为随时可能会有删除字符的操作qwq。
调用一个字符串子串$S[l,r]$的哈希值。复杂度是$O(1)$的。$p$数组是131的幂次,可提前预处理出来,注意$p[0]=1$。以及注意$p$数组若需要预处理,一定处理到字符串的最大长度。
ull gethash(int l,int r)
{
return f[r]-f[l-]*p[r-l+];
}
如果我们想要得到同一个字符串中的两个子串拼接得到的串的哈希值?
从这个问题开始,我们并不需要死记硬背,而是切身的把字符串当做一个数,用进制的思想解决。举第一个栗子:
在[CTSC2014]企鹅QQ这道题中,我们每次都在枚举把哪一个位置的字符去掉,然后将这个字符左边的字符串和右边的字符串重新拼接成一个新的字符串。
假设我们现在有"$zsyasjttql$“这个字符串,我们现在删去第4个位置的“a”,欲得到“$zsysjttql$”,而且我们已经处理了所有前缀的哈希值。那么我们就可以用第一个子串的哈希值乘$131^{len-4}$,类似把一个数分开的操作,在加上第二个字符串的哈希值,就能得到新字符串的哈希值。
Warning?
$strlen$操作是$O(n)$的?所以尽量不要多次调用,而是一次解决。一不小心在循环里可能就会搞成$O(n^2)$的qwq.
$hash$是关键字啦qwqwq,还是尽量避讳的好。
例题
例1
LuoguP3121 [USACO15FEB]审查(黄金)Censoring (Gold)【Hash做法】By cellur925
例2
[CTSC2014]企鹅QQ
给 n 个字符串,如果两个字符串只有同一个位置的字符不相同,那
么称这两个字符串是相似的。
字符串的长度都相等,并且字符串两两不同。
求一共有多少对相似字符串。
n ≤ 30000; |Si| ≤ 200,时间限制 2 秒。
可以枚举删去字符的位置,然后再比较他们的哈希值。
Code
#include<cstdio>
#include<algorithm>
#include<cstring> using namespace std;
typedef unsigned long long ull; int n,l,s;
long long ans;
char tmp[];
ull f[][],p[],tong[]; ull gethash(int u,int l,int r)
{
return f[u][r]-f[u][l-]*p[r-l+];
} int main()
{
p[]=;
scanf("%d%d%d",&n,&l,&s);
for(int i=;i<=n;i++)
{
scanf("%s",tmp+);
int len=strlen(tmp+);
for(int j=;j<=len;j++)
f[i][j]=f[i][j-]*+tmp[j],p[j]=p[j-]*;
}
for(int pos=;pos<=l;pos++)
{
for(int i=;i<=n;i++)
{
ull ha1=gethash(i,,pos-);
ull ha2=gethash(i,pos+,l);
tong[i]=ha1*p[l-pos]+ha2;
}
sort(tong+,tong++n);
int noww=;
for(int pos=;pos<=n;pos++)
if(tong[pos]==tong[pos-]) ans+=noww,noww++;
else noww=;
}
printf("%lld",ans);
return ;
}
总结
哈希还是很简单的知识,但是需要灵活运用。只要把字符串当做一个纯洁的数字,再按照数的方式构造乱搞就行了。虽然我不会别的高级字符串算法(逃),但是灵活使用哈希也可以补充智商不够没学过那么多算法的缺陷嘛(逃)
浅谈字符串哈希 By cellur925的更多相关文章
- 浅谈字符串Hash
浅谈字符串Hash 本篇随笔讲解Hash(散列表)的一个重要应用:字符串Hash. 关于Hash Hash是一种数据结构,叫做Hash表(哈希表),也叫散列表.关于Hash的实现,其实与离散化颇为类似 ...
- 浅谈一致性哈希(My转)
一致性哈希(Consistent hashing)算法是由 MIT 的Karger 等人与1997年在一篇学术论文(<Consistent hashing and random trees: d ...
- 浅谈欧拉函数 By cellur925
1.某神犇Blog 学了三遍的 欧拉函数φ--DEADFISH7 2.我要做一些补充o(* ̄▽ ̄*)o $φ(1)=1$: 公式有两种形式,一种有太多除法,实际可能会慢些.通用 对于任意$n$> ...
- 浅谈并查集 By cellur925【内含题目食物链、银河英雄传说等】
什么是并查集? 合并!查询!集合! 专业点说? 动态维护若干不重叠的和,支持合并查询的数据结构!(lyd老师说的) 数据结构特点:代表元.即为每个集合选择一个固定的元素,作为整个集合的代表,利用树形结 ...
- c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程
c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...
- 浅谈 js 字符串之神奇的转义
原文:浅谈 js 字符串之神奇的转义 字符串在js里是非常常用的,但是你真的了解它么?翻阅<MDN String>就可以了解它的常见用法了,开门见山的就让你了解了字符串是怎么回事. 'st ...
- 浅谈 js 字符串 trim 方法之正则篇
原文:浅谈 js 字符串 trim 方法之正则篇 关于 trim 其实没啥好说的,无非就是去除首位空格,对于现代浏览器来说只是简单的正则 /^\s+|\s+$/ 就可以搞定了.而且支持中文空格 等 ...
- 浅谈 js 字符串 search 方法
原文:浅谈 js 字符串 search 方法 这是一个很久以前的事情了,好像是安心兄弟在学习js的时候做的练习.具体记不清了,今天就来简单分析下 search 究竟是什么用的. 从字面意思理解,一个是 ...
- 浅谈python字符串存储形式
http://blog.csdn.net/zhonghuan1992 钟桓 2014年8月31日 浅谈python字符串存储形式 记录一下自己今的天发现疑问而且给出自己现有知识有的回答. 长话短说,用 ...
随机推荐
- app具体介绍界面-01
在我们的上一篇博客中,我们介绍了首页中的app列表界面怎样完毕.这个ListView以及其Adapter会在我们后面的界面中重用,所以这个是比較重要的,在这一篇博客中,我们先完毕app具体介绍界面的一 ...
- iOS文件的管理(添加,删除,拷贝,移动)
#import "ViewController.h" @implementation ViewController - (void)viewDidLoad { [super vie ...
- javascript参数arguments对象
ECMAScript函数的参数与大多树其他语言中函数的参数有所不同.ECMAScript函数不介意传递进来多少个参数,也不在乎传进来参数是什么类型.函数体是通过arguments对象来访问参数数组.a ...
- deepin os 15.4 切换jdk版本
sudo update-alternatives --config javasudo update-alternatives --config javacsudo update-alternative ...
- ajax的异步操作及页面重定向跳转
今天主要分享一个简单的ajax的异步操作数据,用javascript也有一段时间了,刚开始看到一些页面在没有页面刷新的情况下就可以实现数据的保存或者获取,觉得挺不可思议的,感觉速度很快,做了几个项目之 ...
- 【ACdream】1157 Segments cdq分治
Segments Problem Description 由3钟类型操作:1)D L R(1 <= L <= R <= 1000000000) 增加一条线段[L,R]2)C i ...
- Continuous integration: The answer to life, the universe, and everything?
Continuous integration is not always the right answer. Here's why. https://techbeacon.com/continuous ...
- easyui tree的简单使用
Tree 数据转换 所有节点都包含以下属性: id:节点id,这个很重要到加载远程服务器数据 which is important to load remote data text: 显示的节点文本 ...
- HDU1495 非常可乐 —— BFS + 模拟
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1495 非常可乐 Time Limit: 2000/1000 MS (Java/Others) M ...
- YTU 2577: 小数计算——结构体
2577: 小数计算--结构体 时间限制: 1 Sec 内存限制: 128 MB 提交: 978 解决: 647 题目描述 小数可以看成是一个点和两个数组成的,因此可以定义成一个小数的结构体,现在 ...