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

  哈希大家都会用撒,字符串显然都会写撒,那么哈希离散化字符串不就懂了?!(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. 安装Sql Server 2008时出错

           在安装Sql Server 2008的时候,出现一个错误,说是"SQL Server 2005 Express tools"安装了,需要移除,但是我在控制面板里面找了 ...

  2. (1)分布式下的爬虫Scrapy应该如何做-安装

    关于Scrapy的安装,网上一搜一大把,一个一个的安装说实话是有点麻烦,那有没有一键安装的?答案显然是有的,下面就是给神器的介绍: 主页:http://conda.pydata.org/docs/ 下 ...

  3. Linux 文件属性及修改权限

    输入 ll 或 ls -l 命令显示当前目录中文件的属性及文件所属的用户和组 root@user:/home/www# ll test total 880 drwxr-xr-x 2 root root ...

  4. MySQL☞dual虚拟表

    Dual表:虚拟表,专门用来测试各种函数:(本来以为跟Oracle中的dual表一样,发现还是不太一样)

  5. 分词(Tokenization) - NLP学习(1)

    自从开始使用Python做深度学习的相关项目时,大部分时候或者说基本都是在研究图像处理与分析方面,但是找工作反而碰到了很多关于自然语言处理(natural language processing: N ...

  6. day-10 sklearn库实现SVM支持向量算法

    学习了SVM分类器的简单原理,并调用sklearn库,对40个线性可分点进行训练,并绘制出图形画界面. 一.问题引入 如下图所示,在x,y坐标轴上,我们绘制3个点A(1,1),B(2,0),C(2,3 ...

  7. sed-awk命令详解

      第2章 ***********sed***********. 1目  录 2.1 -------sed命令小结及小结图---- 1 2.2 -------第几行---------- 2 2.3 - ...

  8. vue实战(一):利用vue与ajax实现增删改查

    vue实战(一):利用vue与ajax实现增删改查: <%@ page pageEncoding="UTF-8" language="java" %> ...

  9. WCF服务全局异常处理机制

    服务端增加WCF服务全局异常处理机制,任一WCF服务或接口方式出现异常,将统一调用WCF_ExceptionHandler.ProvideFault方法,因此不需要每个方法使用try catch写法. ...

  10. JavaScript constructor 属性详解

    对象的constructor属性用于返回创建该对象的函数,也就是我们常说的构造函数. 在JavaScript中,每个具有原型的对象都会自动获得constructor属性.除了arguments.Enu ...