前言

蒟蒻最近在复习字符串算法...但正如之前所说,我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的更多相关文章

  1. 浅谈字符串Hash

    浅谈字符串Hash 本篇随笔讲解Hash(散列表)的一个重要应用:字符串Hash. 关于Hash Hash是一种数据结构,叫做Hash表(哈希表),也叫散列表.关于Hash的实现,其实与离散化颇为类似 ...

  2. 浅谈一致性哈希(My转)

    一致性哈希(Consistent hashing)算法是由 MIT 的Karger 等人与1997年在一篇学术论文(<Consistent hashing and random trees: d ...

  3. 浅谈欧拉函数 By cellur925

    1.某神犇Blog 学了三遍的 欧拉函数φ--DEADFISH7 2.我要做一些补充o(* ̄▽ ̄*)o $φ(1)=1$: 公式有两种形式,一种有太多除法,实际可能会慢些.通用 对于任意$n$> ...

  4. 浅谈并查集 By cellur925【内含题目食物链、银河英雄传说等】

    什么是并查集? 合并!查询!集合! 专业点说? 动态维护若干不重叠的和,支持合并查询的数据结构!(lyd老师说的) 数据结构特点:代表元.即为每个集合选择一个固定的元素,作为整个集合的代表,利用树形结 ...

  5. c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程

    c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...

  6. 浅谈 js 字符串之神奇的转义

    原文:浅谈 js 字符串之神奇的转义 字符串在js里是非常常用的,但是你真的了解它么?翻阅<MDN String>就可以了解它的常见用法了,开门见山的就让你了解了字符串是怎么回事. 'st ...

  7. 浅谈 js 字符串 trim 方法之正则篇

    原文:浅谈 js 字符串 trim 方法之正则篇 关于 trim 其实没啥好说的,无非就是去除首位空格,对于现代浏览器来说只是简单的正则 /^\s+|\s+$/ 就可以搞定了.而且支持中文空格   等 ...

  8. 浅谈 js 字符串 search 方法

    原文:浅谈 js 字符串 search 方法 这是一个很久以前的事情了,好像是安心兄弟在学习js的时候做的练习.具体记不清了,今天就来简单分析下 search 究竟是什么用的. 从字面意思理解,一个是 ...

  9. 浅谈python字符串存储形式

    http://blog.csdn.net/zhonghuan1992 钟桓 2014年8月31日 浅谈python字符串存储形式 记录一下自己今的天发现疑问而且给出自己现有知识有的回答. 长话短说,用 ...

随机推荐

  1. addEventListener event

    addEventListener   先看个例子: document.getElementById("myBtn").addEventListener("click&qu ...

  2. maven插件介绍之maven-jar-plugin

    maven-jar-plugin 插件的maven依赖为: <dependency> <groupId>org.apache.maven.plugins</groupId ...

  3. SPOJ VLATTICE Visible Lattice Points (莫比乌斯反演基础题)

    Visible Lattice Points Consider a N*N*N lattice. One corner is at (0,0,0) and the opposite one is at ...

  4. 常用shell命令的写法

    这并不是教人怎么进行shell编程的文章,只是韦哥在工作中用到的一些简单脚本的写法.因为有些命令即使用过几次了,再次使用时仍然写不对,需要man来看下或者需要google,你也可以理解为对命令的理解不 ...

  5. xamarin.android listview绑定数据及点击事件

    前言 listview是用来显示数据列表的一个控件,今天给大家带来如何使用cursor进行数据绑定以及点击事件. 导读 1.如何创建一个listview 2.如何使用cursor进行绑定数据 3.li ...

  6. sqlldr trailing nullcols

    由于要导入到tmp_content表的一些列(列:要导入的源文件txt or csv文件)为空,也,按理讲我当时另存为(在windows处理)csv,以,分隔.就是这个列没有内容,也该显示, ,之类的 ...

  7. BZOJ2327: [HNOI2011]勾股定理

    BZOJ2327: [HNOI2011]勾股定理 Description 题解Here! 这是一道神题... 我一开始把题目看错了,我以为是在$n$根木棒中选两个$i,j$满足$gcd(i,j)==1 ...

  8. linux内存操作--ioremap和mmap

    最近在做视频输出相关的东西,对于预留给framebuffer的内存使用不是很清楚,现在找到一些资料整理一下,以备使用.if (想看使用方法)  goto   使用方法: 对于一个系统来讲,会有很多的外 ...

  9. bzoj3134: [Baltic2013]numbers

    稍微用脑子想一想,要是一个回文数,要么s[i]==s[i+1]要么s[i]==s[i+2]就可以实锤了 所以多开两维表示最近两位选的是什么数就完了 注意前导0 #include<cstdio&g ...

  10. Hihocoder 之 #1097 : 最小生成树一·Prim算法 (用vector二维 模拟邻接表,进行prim()生成树算法, *【模板】)

    #1097 : 最小生成树一·Prim算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可 ...