浅谈字符串哈希 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字符串存储形式 记录一下自己今的天发现疑问而且给出自己现有知识有的回答. 长话短说,用 ...
随机推荐
- 【转载】分布式RPC框架性能大比拼
dubbo.motan.rpcx.gRPC.thrift的性能比较 Dubbo 是阿里巴巴公司开源的一个Java高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 ...
- iOS应用崩溃日志分析 iOS应用崩溃日志揭秘
转自:http://www.raywenderlich.com/zh-hans/30818/ios%E5%BA%94%E7%94%A8%E5%B4%A9%E6%BA%83%E6%97%A5%E5%BF ...
- Posix信号量操作函数
Posix信号量: 分类: Posix有名信号量:使用Posix IPC名字标识,可用于线程或进程间同步Posix基于内存的信号量:存放在共享内存区中,可用于进程或线程间的同步 sem_open(). ...
- HDU 3065 病毒侵袭持续中(AC自己主动机)
题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=3065 Problem Description 小t非常感谢大家帮忙攻克了他的上一个问题.然而病毒侵袭 ...
- Centos6-编译安装Redis
[root@tbwy02 ~]# cd /tools/[root@tbwy02 tools]# yum install -y wget gcc make tcl[root@tbwy02 tools]# ...
- Entity Framework 6 Code First 实践系列(1):实体类配置-根据依赖配置关系和关联
EF实体类的配置可以使用数据注释或Fluent API两种方式配置,Fluent API配置的关键在于搞清实体类的依赖关系,按此方法配置,快速高效合理.为了方便理解,我们使用简化的实体A和B以及A.B ...
- javascript模块化编程:CommonJS和AMD规范
AMD规范,异步模块定义.与CommonJS规范齐名并列. 作用都是利于JavaScript的模块化编程. 模块化编程的好处就是: 1.可重用 2.独立 3.能解决加载的依赖性问题 4.能解决重复加载 ...
- Tomcat安全配置规范
第1章 账号管理.认证授权 1.1 账号 1.1.1 共享帐号管理 安全基线项目名称 Tomcat共享帐号管理安全基线要求项 安全基线编号 SBL-Tomcat-01-01-01 安全基线项说明 ...
- LOJ#139. 树链剖分
LOJ#139. 树链剖分 题目描述 这是一道模板题. 给定一棵$n$个节点的树,初始时该树的根为 1 号节点,每个节点有一个给定的权值.下面依次进行 m 个操作,操作分为如下五种类型: 换根:将一个 ...
- 百度dureos CMake Error
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage CMake Error: CMAKE_CXX_COMPILER not set, ...