本文含有原创题,涉及版权利益问题,严禁转载,违者追究法律责任

  哈希大家都会用撒,字符串显然都会写撒,那么哈希离散化字符串不就懂了?!(XXX的神逻辑,其实原文是:树都晓得吧,数组显然都会开呀,那么恭喜你学会了树状数组!)

  例如我们给出 n 个长度为 m 的字符串,然后给你一个长度为 m 的字符串 s ,求 s 是否在之前的 n 个串中出现过

  暴力扫 n 个串,然后一位位去对,看是否相等,时间复杂度O(nm),它非常得辣鸡

  当然我们可以建一颗 trie 树做,但是建树的复杂度也是O(nm)的,对于只询问一次还不如打暴力

  一阵思考后,我们选用非常优秀的哈希(以下简称Hash)

  (机制的人请忽略这篇文章)

  平常我们用 Hash 是对数字进行处理,一般把它取模之后离散化到各个数组

  但是对于字符串呢?难道把它所有位加起来取模?显然是不行的,如 ab 和 ba 这两种情况是相同的,那么小节点挂的链会很多

  于是乎,我们想,对于字符串只有256种,而题目中给的一般只会包含字母,甚至是只有小写字母,瞬间压缩到26种

  那么我们可以把它前面 k 位取出来,如取4位出来是 axoc,把它装换成对应的数字是 0 23 14 2 (a 看做 0,b 看做 1 …… z 看做 25)

  这不就是一个二十六进制数!

  把前 k 位取出来,第 i 位即为这个26进制数的第 i 位,再把它转换为10进制,如 axoc 为 45214,这样我们就得到了 Hash 的 Hash 函数了

  字符串判重就容易了, Hash 具体实现过程就不用讲了吧

  对于 26 进制的数,int 范围下只能取到第 6 位,long long范围下可以取到第 13 位

    

  下面给道例题

  题意很简单,给你一个串,求他有多少个不同的子串,满足前缀为A,后缀为B。 需要注意的是,串中所有的字母都是小写字母。

  三个串长度均小于等于 2000,时间1s,空间128MB

  样例输入:abababab

       a

       b

  样例输出:4

  直接暴力枚举然后 Hash 判重,我们这里截取前3位做 Hash 函数

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std; const int N=,loc=,power[]={,,,,,,,},mo=;
struct Hash
{
int next;
char s[N];
}
hs[N*];
char a[N],b[N],s[N];
int ls,ans,next[N],f[N],top,first[mo],tg,g[mo];
bool fa[N],fb[N];
void init(char c[N],int len)
{
int i,j=;
for (i=;i<len;i++)
{
while (j&&c[i]!=c[j]) j=next[j];
if (c[i]==c[j]) j++;
next[i+]=j;
}
}
void kmp(char c[N],int len)
{
int i,j=;
top=;
for (i=;i<=len;i++) next[i]=;
init(c,len);
for (i=;i<ls;i++)
{
while (j&&s[i]!=c[j]) j=next[j];
if (s[i]==c[j]) j++;
if (j==len)
{
f[++top]=i-j+;
j=next[j];
}
}
}
void hash(char c[N],int len)
{
int i,x=,t=min(len,loc);
for (i=;i<=t;i++) x+=(c[i]-'a')*power[i];
if (first[x]) for (i=first[x];i;i=hs[i].next)
{
t=len-loc;
if (t<=) return;
for (x=;x<=t;x++) if (hs[i].s[x]!=c[loc+x]) break;
if (x>t) return;
}
if (!(hs[++top].next=first[x])) g[++tg]=x;
first[x]=top;
x=;
for (i=loc+;i<=len;i++) hs[top].s[++x]=c[i];
ans++;
}
int main()
{
int la,lb,i,j,t,x,k,l;
char c[N];
scanf("%s\n%s\n%s\n",&s,&a,&b);
ls=strlen(s);
la=strlen(a);
lb=strlen(b);
kmp(a,la);
for (i=;i<=top;i++) fa[f[i]]=;
kmp(b,lb);
for (i=;i<=top;i++) fb[f[i]]=;
t=ls-la-lb;
for (j=;j<=t;j++)
{
for (i=;i<=tg;i++) first[g[i]]=;
top=tg=;
for (i=;i<=t-j;i++)
{
x=i+j+la;
if (fa[i]&&fb[x])
{
l=;
for (k=i+la;k<x;k++) c[++l]=s[k];
hash(c,j);
}
}
}
for (i=max(la-lb-,);i<=la;i++)
{
j=i;
while (a[j]==b[j-i]) j++;
if (a[j]!='\0') continue;
for (j=;j<i;j++) c[j]=a[j];
for (k=;k<lb;k++,j++) c[j]=b[k];
kmp(c,j);
if (top) ans++;
}
printf("%d\n",ans);
return ;
}

  据说可以用KMP或者EXKMP做orz

  还有我的程序在 Hash 取别的位数的时候会 WA 几个点(而且还是不同的点??)

  求助大神能解释一下orz(再次体现我的蒟蒻)

  注:该题为原创题,可购买数据,价格 RMB 2.0

  如需购买在这 Get 联系方式  http://www.cnblogs.com/hadilo/p/5932395.html

哈希Hash在字符串中的应用_C++的更多相关文章

  1. Redis中的哈希(Hash)

    Redis 哈希(Hash) Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象. Redis 中每个 hash 可以存储 232 - 1 键值 ...

  2. Redis 命令,键(key),字符串(String),哈希(Hash),列表(List),集合(Set)(二)

      Redis 命令 Redis 命令用于在 redis 服务上执行操作. 要在 redis 服务上执行命令需要一个 redis 客户端.Redis 客户端在我们之前下载的的 redis 的安装包中. ...

  3. Crazy Search POJ - 1200 (字符串哈希hash)

    Many people like to solve hard puzzles some of which may lead them to madness. One such puzzle could ...

  4. 牛客练习赛33 E tokitsukaze and Similar String (字符串哈希hash)

    链接:https://ac.nowcoder.com/acm/contest/308/E 来源:牛客网 tokitsukaze and Similar String 时间限制:C/C++ 2秒,其他语 ...

  5. hash数组快速查找一个字符串中出现最多的字符,并统计出现的次数

    如何快速查找一个字符串中出现最多的字符,并统计出现的次数? 可以使用hash数组,也就是关联数组实现快速查找功能. function seek(str) { var hash = []; var ma ...

  6. 大话Java中的哈希(hash)结构(一)

    o( ̄▽ ̄)d 小伙伴们在上网或者搞程序设计的时候,总是会听到关于“哈希(hash)”的一些东西.比如哈希算法.哈希表等等的名词,那么什么是hash呢? 一.相关概念 1.hash算法:一类特殊的算法 ...

  7. 面试35-删除字符串重复字符-删除出现在第二个字符串中的字符-第一个只出现一次的字符-hash表计数

    #include<iostream>#include<algorithm>#include<functional>using namespace std;char ...

  8. 萌新笔记——Cardinality Estimation算法学习(一)(了解基数计算的基本概念及回顾求字符串中不重复元素的个数的问题)

    最近在菜鸟教程上自学redis.看到Redis HyperLogLog的时候,对"基数"以及其它一些没接触过(或者是忘了)的东西产生了好奇. 于是就去搜了"HyperLo ...

  9. redis 哈希(hash)函数

    哈希(hash)函数 hSet 命令/方法/函数 Adds a value to the hash stored at key. If this value is already in the has ...

随机推荐

  1. Java Web前后端分离的思考与实践

    第一节 Java Web开发方式的变化 Web开发虽然是我们常说的B/S模式,其实本质上也是一种特殊的C/S模式,只不过C和S的选择余地相对要窄了不少,而且更标准化.不论是采用什么浏览器和后端框架,W ...

  2. 07-Mysql数据库----数据类型

    介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 详细参考链接:http://www.runoob.com/mysql/mysql-data- ...

  3. 第一周 Introduction

    欢迎 欢迎来到这门关于机器学习的免费网络课程,机器学习是近年来最激动人心的技术之一,在这门课中,你不仅可以了解机器学习的原理,更有机会进行实践操作,并且亲自运用所学的算法. 每天你都可能在不知不觉中使 ...

  4. To Chromium之版本管理

    Git. 1.由于想直接submit到Chromium的官方Branch需要申请权限,目前拿不到,所以打算snapshot一个chromium版本. 本地搭建一个git的server/client,方 ...

  5. tomcat 路径"/"表示根目录

  6. 【bzoj2453】维护队列/【bzoj2120】数颜色 分块+二分

    题目描述 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好, ...

  7. 'com.alibaba.fastjson.support.spring.FastJsonpResponseBodyAdvice' is。。。。

    com.alibaba.fastjson版本1.2.43版本在通过xml方式配置spring的时候会出现这个个奇怪的问题: Class 'com.alibaba.fastjson.support.sp ...

  8. poj 2965 The Pilots Brothers' refrigerator (dfs)

    The Pilots Brothers' refrigerator Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17450 ...

  9. 【题解】NOI2017游戏

    2-SAT.洛谷P3845 一开始以为——怎么有3个呢?后来发现因为每个地图都有一种车是不能用的,所以就等于每一个地图都有两个适应的车啦. 那么对于x类型的地图呢——只有8个,直接2^8暴力枚举每一种 ...

  10. 【题解】JSOI2010满汉全席

    ~bzoj1823 第一次接触2-SAT——SAT,即适定性(Satisfiability)的缩写.像名称所说,即满足需求的可能性问题,而k-SAT即每个人有k种需求,已经证明k>2时是一个NP ...