Hash大法
内容参考《算法竞赛进阶指南》
之前集训的时候听老师讲过,字符串题目中,hash一般不是正解,但是是一个优秀的暴力,可以拿比较多的部分分。
hash涉及内容很多,这里只讨论字符串hash
可以把字符串看成一个131进制位数,然后用ull储存,大过2的64次方后自动取模。
这样的话hash值相等的话可以认为两个字符串是一样的(极少概率不一样)
所以对于一个字符串,我们可以用O(n)的时间内算出所有前缀的hash值,然后就可以用
O(1)的时间算出任意一段区间的hash值(类比二进制操作,具体看代码)。
Hash大法吼啊!!!
怎么用呢?
问题:给你一个字符串,每次询问两个区间[l1, r1][l2, r2],判断两个区间的字符是否相等
#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;
typedef unsigned long long ull;
const int MAXN = 1e6 + 10;
const int base = 131;
char s[MAXN];
int n, q;
ull p[MAXN], f[MAXN];
inline ull cut(int l, int r)
{
return f[r] - f[l - 1] * p[r - l + 1];
}
int main()
{
scanf("%d%d", &n, &q); //n为字符串长度
scanf("%s", s + 1);
p[0] = 1;
_for(i, 1, n)
{
f[i] = f[i - 1] * base + (s[i] - 'a' + 1);
p[i] = p[i - 1] * base;
}
while(q--)
{
int l1, r1, l2, r2;
scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
if(cut(l1, r1) == cut(l2, r2)) puts("Yes");
else puts("No");
}
return 0;
}
用Hash大法解决kmp问题
比较hash值就好了,非常简单粗暴!!!(但效率比KMP慢一些,所以说是一个优秀的暴力)
#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;
typedef unsigned long long ull;
const int MAXN = 1e6 + 10;
const int base = 131;
char a[MAXN], b[MAXN];
int n, q, lena, lenb;
ull p[MAXN], f[MAXN], t;
inline ull cut(int l, int r)
{
return f[r] - f[l - 1] * p[r - l + 1];
}
int main()
{
scanf("%s%s", a + 1, b + 1);
lena = strlen(a + 1); lenb = strlen(b + 1);
p[0] = 1;
_for(i, 1, lena)
{
f[i] = f[i - 1] * base + (a[i] - 'a' + 1);
p[i] = p[i - 1] * base;
}
_for(i, 1, lenb) t = t * base + (b[i] - 'a' + 1);
_for(i, 1, lena)
{
if(cut(i, i + lenb - 1) == t)
{
printf("%d %d\n", i, i + lenb - 1);
break;
}
if(i == lena) puts("NO");
}
return 0;
}
Hash大法的更多相关文章
- hdu5183 hash大法
维护前缀和sum[i]=a[0]-a[1]+a[2]-a[3]+…+(-1)^i*a[i]枚举结尾i,然后在hash表中查询是否存在sum[i]-K的值.如果当前i为奇数,则将sum[i]插入到has ...
- NOIP 2014 D2T3 解方程 Hash大法好
题目大意:给定高次方程an*x^n+...+a1*x^1+a0*x^0=0 求[1,m]区间内有多少个整数根 ai<=10^10000.m<=100W 懒得高精,考场上写的long dou ...
- LeetCodeTwo Sum IV 树的遍历+Hash大法好
题意 给定一颗二叉搜索树,返回是否存在两个节点的值之和为给定值K. 思路 同Two Sum.使用Hash表解决.只是要写个树的遍历而已,选取DFS. 源码 class Solution { publi ...
- POJ 1743 Musical Theme Hash+二分法
标题效果:有一个美丽的旋律,它们是由一些不大于88音调.如果计为五个音调的量度,问:是否有相同的节奏的多个部分(相同的差,以及两者之间的相同的节奏不能重叠),并寻求最长长度. 思考:这个问题是八人中的 ...
- 【线段树 集合hash】bzoj4373: 算术天才⑨与等差数列
hash大法好(@ARZhu):大数相乘及时取模真的是件麻烦事情 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次 ...
- LeetCode longest substring without repeating characters 题解 Hash表
题目 Given a string, find the length of the longest substring without repeating characters. Example 1: ...
- 【Tyvj 1060】【NOIP 2005】等价表达式
设a为一个质数,模数为另一个质数,然后暴力算多项式的答案,如果答案相等就认为两个多项式相等. 这种hash有出错概率的题为什么还是要用hash呢?因为出错的概率实在太小了,a和模数的值取得好出题人根本 ...
- bzoj4264: 小C找朋友
hash大法好 #include <iostream> #include <cstdio> #include <cstring> #include <cmat ...
- bzoj4337: BJOI2015 树的同构
hash大法好 #include <iostream> #include <cstdio> #include <cstring> #include <cmat ...
随机推荐
- c++之vector使用
Vector是向量模板,C++ STL之一(本质上是一个动态数组).vector是一个动态生长的数组,一开始vector为空时,会给一个初始化的容量 (就是允许的添加个数并申请好内存),当往添加的元素 ...
- 《代码敲不队》第八次团队作业:Alpha冲刺 第三天
项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 代码敲不队 作业学习目标 掌握软件编码实现的工程要求. 团队项目github仓库地址链接 GitH ...
- 02018_StringBuffer练习
1.已知int[] arr = {34,12,89,68}; 将其中的元素转成字符串,格式 [34,12,89,68]: 参考:02011_定义打印数组元素方法,按照给定的格式打印[11, 33, 4 ...
- 使用gson进行数据(集合数据)的转换 并且返回给前端 进行动态解析 并添加
后台使用gson转换工具把list集合数据 以json字符串的方式返回给前台 解压: 加入到工程中 前台页面进行数据解析时 需要把得到的字符串 转换为object数组 -------------- ...
- Sping面试题分析
1.开放中主要使用Spring的什么技术? (1)IOC容器管理各层的组件 (2) 使用AOP配置声明式事务 (3)整合其他框架 2简述AOP和IOC概念 AOP : Aspect Orienten ...
- HDU 4358
看了题解那个弱化版后,马上就去做了HDU 3333这道题,发现有可用的地方.于是往这方面想,主要是处理如何确定一个数出现K次的问题.想到了从左往右把每个数出现的次数记下来,但感觉不是这样,呃,再看别人 ...
- PHP--规范化的文件上传
<form action="" method="post" enctype="multipart/form-data"> < ...
- quick-cocos2dx 之transition.execute()的缓动效果
注:本文图片来源(http://hosted.zeh.com.br/tweener/docs/en-us/misc/transitions.html. 侵权请告知,即刻删除) 什么是缓动, 缓动(ea ...
- hdu5319 Painter(模拟)
题目链接:点击打开链接 题目大意:给一个矩形.有两把刷子,一把刷红色,一把刷蓝色,红色的方向是东南,蓝色的方向是西北,红色加蓝色等于绿色,如今已知这面墙当前的状态.求从白墙到这个状态最少刷了多少次. ...
- 求区间连续不超过K段的最大和--线段树+大量代码
题目描述: 这是一道数据结构题. 我们拥有一个长度为n的数组a[i]. 我们有m次操作.操作有两种类型: 0 i val:表示我们要把a[i]修改为val; 1 l r k:表示我们要求出区间[l,r ...