不懂hash是什么的盆友给出直通车:滴滴滴,开车啦~

如果你看懂了的话:

hash模板来也~

#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm> using namespace std; typedef long long LL; const int N = 1e5 + ; //
const int D = ; //质数
const int MD = 1e9 + ; //大质数 int n;
string s; unsigned long long f[N], g[N]; //g[i]为D的i次方 void prehash(int n) //进行预处理
{
// 预处理时,注意到数字可能很大,对一个数 MD 取模
f[] = s[];//预处理前缀和(进行强制类型转)
for(int i=; i<=n; i++)
f[i] = (1LL * f[i-] * D + s[i-]) % MD; g[] = ; //预处理D
for(int i=; i<=n; i++)
g[i] = 1LL * g[i-] * D % MD;
} int hash(int l, int r) //计算区间 [l,r] 的哈希值
{
int a = f[r];
int b = 1LL * f[l-] * g[r-l+] % MD; return (a - b + MD) % MD; //+MD是为了防止出现负数
} int main()
{
cin >> s;
n = s.length();
prehash(n); while(!cin.eof())//直至按ctrl+z键退出!
{
int l, r;
cin >> l >> r;
cout << s.substr(l-, r-l+) << ": " << hash(l, r) << endl;
//从l-1到r-l+1的字符
} return ;
}

良心推荐洛谷练手题:

1.P3370【模板】字符串哈希

题目描述

如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字、大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串。

友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转PJ试炼场:)

输入输出格式

输入格式:

第一行包含一个整数N,为字符串的个数。

接下来N行每行包含一个字符串,为所提供的字符串。

输出格式:

输出包含一行,包含一个整数,为不同的字符串个数。

输入输出样例

输入样例#1:

5
abc
aaaa
abc
abcc
12345
输出样例#1:

4

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=10,Mi≈6,Mmax<=15;

对于70%的数据:N<=1000,Mi≈100,Mmax<=150

对于100%的数据:N<=10000,Mi≈1000,Mmax<=1500

样例说明:

样例中第一个字符串(abc)和第三个字符串(abc)是一样的,所以所提供字符串的集合为{aaaa,abc,abcc,12345},故共计4个不同的字符串。

Tip: 感兴趣的话,你们可以先看一看以下三题:

BZOJ3097:http://www.lydsy.com/JudgeOnline/problem.php?id=3097

BZOJ3098:http://www.lydsy.com/JudgeOnline/problem.php?id=3098

BZOJ3099:http://www.lydsy.com/JudgeOnline/problem.php?id=3099

如果你仔细研究过了(或者至少仔细看过AC人数的话),我想你一定会明白字符串哈希的正确姿势的^_^

思路:

  题解里面是有很多种方法的,但是我认为能够搞懂一种就已经很不错了……

  所以我给出的思路就是用set来进行统计,set只能够允许一种数字出现一次,所以我们就可以将给出的字符串的hash值求出来

  然后加入到set里面,最后直接输出set里面有多少数就行啦~

PS:

      定义函数的时候不要用"hash"这个名字,在洛谷里是关键字!!!

上代码=u=:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <set> using namespace std; typedef unsigned long long ull;
typedef long long LL;
set<ull>ssr; const int N = ;
const int D = ; //质数
const ull MD= 1e9 + ; //大质数 LL n,len;
string s; ull f[N];//预处理前缀和
ull g[N];//预处理 D的i次方 int yuchuli(int q)
{
memset(f,,sizeof(f));
memset(g,,sizeof(g));
f[]=s[];
for(int i=;i<=q;i++)
f[i] = (1LL * f[i-] * D +s[i-]) % MD;
g[]=;
for(int i=;i<=q;i++)
g[i] = 1LL * g[i-] * D % MD;
} int hashs(int l,int r)
{
ull a = f[r];
ull b = 1LL * f[l-] *g[r-l+] % MD; return (a - b + MD) % MD;
} int main()
{
cin>>n;
while(n--)
{
cin>>s;
len=s.length();
yuchuli(len);
ull qq = hashs(,len);
ssr.insert(qq);
}
cout<<ssr.size();
return ;
}  

2.

cogs249. [POI2000] 最长公共子串

★★★   输入文件:pow.in   输出文件:pow.out   简单对比
时间限制:1 s   内存限制:256 MB

给出几个由小写字母构成的单词,求它们最长的公共子串的长度。

任务

  • 从文件中读入单词
  • 计算最长公共子串的长度
  • 输出结果到文件

输入

文件的第一行是整数 n,1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000。

输出:

仅一行,一个整数,最长公共子串的长度。

样例输入:

3
abcb
bca
acbc

样例输出:

2

 思路:

  正解据说是后缀数组呢!后缀数组是什么鬼???我又不会...只好胡乱搞hash啦~结果一搞...奇迹的就WA了一个点,结果又胡乱改了一下Mod,然后就A了...真不可思议w

    Ps:脑洞产物(正解xxx),能不能过全看 your rp!!!

  话不多说:

  hash的思路:

  •       pre:

          首先话不多说,跟普通hash一样把每一个单词的hash值求一下,然后快乐地开始进行二分公共子串的长度

          然后我们又设置了vis和times两个数组,其中times[i]表示当前hash值i已经出现在几个单词里面。
          接着枚举每个单词中子串的开始位置,用O(1)时间求该子串的hash,然后times加一。
          (当然同一个长单词里面可能有相同的子串,所以用vis记录一下这个hash值最后出现在第几个单词中,来判断该子串在当前字符串中是不是第一次出现。)
  •       结束条件:
          如果times加到n了,说明每个单词里面都有这个子串,这个解是正确的,然后顺路更新一下ans的值!
  •       时间复杂度:
          1)求hash是O(|S|*n),|S|表示最长的子串长度。
          2)二分答案部分为(log|S|*n*|S|)。
        故总体的期望复杂度为O(log|S|*|S|*n),而n只有5,|S|只有2000,显然轻松过去..
        over!!!

坑点:

  在选取Mod以及D的时候,一定要多用几组,防止发生冲突。

上代码=v=:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define INF 0x7fffffff
#define LL long long
using namespace std; const int D = ;
const int Mod = ;
const int N = ;
const int le = ;
int n,minl,ans;
LL f[N][le],g[le];
int len[N];
char str[le];
int vis[Mod+],times[Mod+]; bool check(int x)
{
memset(vis,,sizeof(vis));
memset(times,,sizeof(times));
LL cv=g[x];
for(int i=;i<=n;++i)
{
for(int j=x;j<=len[i];++j)
{
LL nowhash=(f[i][j]-(f[i][j-x]*cv)%Mod+Mod)%Mod;
if(vis[nowhash]!=i)
{
++times[nowhash];
vis[nowhash]=i;
if(times[nowhash]==n)
return true;
}
}
}
return false;
} void prehash(int i)
{
f[i][]=str[]-'a'+;
for(int j=;j<=len[i];++j)
f[i][j]=(f[i][j-]*D+(str[j-]-'a'+))%Mod;
} void dichotomy()
{
int l=,r=minl+;
while(l<r)
{
int mid=(l+r)>>;
if(check(mid))
ans=mid,l=mid+;
else
r=mid;
}
printf("%d",ans);
} int main()
{
freopen("pow.in", "r", stdin);
freopen("pow.out", "w", stdout);
scanf("%d",&n);
minl=INF;
for(int i=;i<=n;++i)
{
scanf("%s",str);
len[i]=strlen(str);
if(len[i]<minl) minl=len[i];
prehash(i);
}
g[]=;
for(int i=;i<=minl;++i)
g[i]=1LL*g[i-]*D%Mod;
dichotomy();
return ;
}

【テンプレート】字符串hash的更多相关文章

  1. [知识点]字符串Hash

    1.前言 字符串的几大主要算法都多少提及过,现在来讲讲一个称不上什么算法, 但是非常常用的东西——字符串Hash. 2.Hash的概念 Hash更详细的概念不多说了,它的作用在于能够对复杂的状态进行简 ...

  2. 【BZOJ-3555】企鹅QQ 字符串Hash

    3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1545  Solved: 593[Submit][Statu ...

  3. POJ 1200 字符串HASH

    题目链接:http://poj.org/problem?id=1200 题意:给定一个字符串,字符串只有NC个不同的字符,问这个字符串所有长度为N的子串有多少个不相同. 思路:字符串HASH,因为只有 ...

  4. LA4671 K-neighbor substrings(FFT + 字符串Hash)

    题目 Source http://acm.hust.edu.cn/vjudge/problem/19225 Description The Hamming distance between two s ...

  5. 各种字符串Hash函数比较(转)

    常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎 ...

  6. 字符串hash + 二分答案 - 求最长公共子串 --- poj 2774

    Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在 ...

  7. 字符串hash - POJ 3461 Oulipo

    Oulipo Problem's Link ---------------------------------------------------------------------------- M ...

  8. 长度有限制的字符串hash函数

    长度有限制的字符串hash函数 DJBHash是一种非常流行的算法,俗称"Times33"算法.Times33的算法很简单,就是不断的乘33,原型如下 hash(i) = hash ...

  9. hdu 4622 Reincarnation 字符串hash 模板题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意:给定一个长度不超过2000的字符串,之后有不超过1e5次的区间查询,输出每次查询区间中不同 ...

  10. [转]各种字符串Hash函数比较

    转自:https://www.byvoid.com/zht/blog/string-hash-compare 常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些 ...

随机推荐

  1. Android--单选对话框

    import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterfa ...

  2. sass快速使用

    sass的使用 建议使用一种语法格式(scss) scss sass转换 sass-convert main.scss main.sass sass变量声明 example: $headline-ff ...

  3. 细说浏览器输入URL后发生了什么

    本文摘要: 1.DNS域名解析: 2.建立TCP连接: 3.发送HTTP请求: 4.服务器处理请求: 5.返回响应结果: 6.关闭TCP连接: 7.浏览器解析HTML: 8.浏览器布局渲染: 总结   ...

  4. window服务器查看管理员列表

    快捷键win+R 输入cmd并进入 输入指令net localgroup administrators

  5. 2019牛客多校八 H. How Many Schemes (AC自动机,树链剖分)

    大意: 给定树, 每条边有一个字符集合, 给定$m$个模式串, $q$个询问$(u,v)$, 对于路径$(u,v)$中的所有边, 每条边从对应字符集合中取一个字符, 得到一个串$s$, 求$s$至少包 ...

  6. sublime text3 关闭更新提醒

    Preferences->settings 在Preferences.sublime-setting --User中 增加: "update_check":false,

  7. 本地数据存储解决方案以及cookie的坑

    本地数据存储解决方案以及cookie的坑 问题: cookie过长导致页面打开失败 背景: 在公司的项目中有一个需求是打开多个工单即在同一个页面中打开了多个tab(iframe),但是需要在刷新时只刷 ...

  8. Java 之 Junit 单元测试

    Junit 单元测试 测试分类: 1.黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值. 2.白盒测试:需要写代码.关注程序具体的执行流程. Junit 测试:(属于白盒测试) 步骤: 1 ...

  9. Django 启动报错 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc7

    pycharm 报错 cmd 报错 解决办法 首先 是计算机 编码问题  是 django 读取你的  用户host名 但是 windos 用户名 如果是中文 就会报这个错  要改成 英文

  10. 简述FTP的主动模式与被动模式(精简)

    一.主被动 主动: 客户端从任意一个大于1024的端口现在假设为1234(非特权端口)连接到服务端的21端口(命令端口),随之客户端监听端口(N+1)即为1235端口(可以理解为这是客户端认定的数据端 ...