字符串hash&&对字符串hash的理解
对字符串hash的一些总结:
1,首先,我们在转化的时候,取底的时候一般是取131这些数,因为要避免不同的字符串对应相同的hash值这种情况的出现。如果卡精度的时候,我们可以采取双模数的方式尽量减少误差,(不过这种东西还是得看脸)。
2,在定义的时候,一般是为了定义成unsigned long long ,这个有一个好处,当爆int的时候,不会带上负号,就相当于对2的64次方进行取模了。
3.在进行hash的转换的时候,字符串对应的0位,hash值不是0,所以我们可以先将字符串往后移动一位再去赋值。
4,我们将一个整的字符串计算好hash值的时候,如果要取(l,r)这段区间的子串的hash值,可以采用以下公式。
ans = hash[r] - hash[l-1]*ind[r-l+1];
A
单模数hash
题目链接:https://www.luogu.org/problemnew/show/P3370
具体思路:我们可以将字符串的每一个字符转换成数字,然后比较的时候,直接比较这个字符串对应的hash值就可以了。
AC代码:
#include<iostream>
#include<stdio.h>
#include<iomanip>
#include<stack>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;
# define ll long long
# define ull unsigned long long
const int base=;//一般比ascii码值大就可以了。
const int maxn = 1e4+;
char str[maxn];
ll a[maxn];
ull Hash(char a[])
{
int len=strlen(a);
ull sum=;
for(int i=; i<len; i++)
{
sum=sum*base+(ull)a[i];
}
return sum;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=; i<=n; i++)
{
scanf("%s",str);
a[i]=Hash(str);
}
sort(a+,a+n+);
int ans=;
for(int i=; i<=n; i++)
{
if(a[i]!=a[i-])
ans++;
}
printf("%d\n",ans);
return ;
}
双模数hash
#include<iostream>
#include<stdio.h>
#include<iomanip>
#include<stack>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;
# define ll long long
# define ull unsigned long long
const int mod1=1e9+;
const int mod2=1e9+;
const int base=;
const int maxn = 1e4+;
char str[maxn];
struct node{
ull t1;
ull t2;
}q[maxn];
bool cmp(node s1,node s2){
return s1.t1<s2.t1;
}
ull hash1(char *a){
ull sum=;
int len=strlen(a);
for(int i=;i<len;i++){
sum=(sum*base+(ull)a[i])%mod1;
}
return sum;
}
ull hash2(char *a){
ull sum=;
int len=strlen(a);
for(int i=;i<len;i++){
sum=(sum*base+(ull)a[i])%mod2;
}
return sum;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=; i<=n; i++)
{
scanf("%s",str);
q[i].t1=hash1(str);
q[i].t2=hash2(str);
}
sort(q+,q+n+,cmp);
int ans=;
for(int i=;i<=n;i++){
if(q[i].t1!=q[i-].t1||q[i].t2!=q[i-].t2)ans++;
}
printf("%d\n",ans);
return ;
}
B题:
题目链接:https://cn.vjudge.net/contest/276379#problem/J
题目大意:这本来是一道kmp的模板题,然后今下午打算用字符串hash做一下,结果一下午过去了,,,,
具体思路:和拓展kmp的方法相同,就是比较的时候直接比较子串的hash值就可以了。
AC代码:
#include<iostream>
#include<stdio.h>
#include<iomanip>
#include<stack>
#include<algorithm>
#include<map>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;
# define ll long long
# define ull unsigned long long
const int mod1=1e9+;
const int mod2=1e9+;
const ull base=;
const int maxn = 1e5+;
char str1[maxn],str2[maxn],com[];
ull hash1[maxn],hash2[maxn],ind[maxn];
map<char,char>vis;
void init()
{
ind[]=;
for(int i=; i<maxn; i++)
{
ind[i]=ind[i-]*base;
}
}
void hs1(char *a)
{
int len=strlen(a+);
hash1[]=;
for(int i=; i<=len; i++)
{
hash1[i]=hash1[i-]*base+(ull)a[i];
}
}
void hs2(char *a)
{
int len=strlen(a+);
hash2[]=;
for(int i=; i<=len; i++)
{
hash2[i]=hash2[i-]*base+(ull)a[i];
}
}
ull getsub1(int l,int r)
{
return hash1[r]-hash1[l-]*ind[r-l+];
}
ull getsub2(int l,int r)
{
return hash2[r]-hash2[l-]*ind[r-l+];
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",com);
scanf("%s",str1+);
for(int i=; i<; i++)
{
vis[com[i]]=char('a'+i);
}
int len=strlen(str1+);
for(int i=; i<=len; i++)
{
str2[i]=vis[str1[i]];
}
hs1(str1);
hs2(str2);
int ans=len;
for(int i=len; i<len+len; i++)
{
if(i&)continue;
int tmp=i/;
ull t1=getsub2(,len-tmp);
ull t2=getsub1(len-(len-tmp)+,len);
if(t1==t2)
{
ans=tmp;
break;
}
}
for(int i=; i<=ans; i++)
{
printf("%c",str1[i]);
}
for(int i=; i<=ans; i++)
{
printf("%c",str2[i]);
}
printf("\n");
}
return ;
}
字符串hash&&对字符串hash的理解的更多相关文章
- 转载:字符串hash总结(hash是一门优雅的暴力!)
转载自:远航休息栈 字符串Hash总结 Hash是什么意思呢?某度翻译告诉我们: hash 英[hæʃ] 美[hæʃ]n. 剁碎的食物; #号; 蔬菜肉丁;vt. 把…弄乱; 切碎; 反复推敲; 搞糟 ...
- cdoj1092-韩爷的梦 (字符串hash)【hash】
http://acm.uestc.edu.cn/#/problem/show/1092 韩爷的梦 Time Limit: 200/100MS (Java/Others) Memory Limi ...
- 字符串学习总结(Hash & Manacher & KMP)
前言 终于开始学习新的东西了,总结一下字符串的一些知识. NO.1 字符串哈希(Hash) 定义 即将一个字符串转化成一个整数,并保证字符串不同,得到的哈希值不同,这样就可以用来判断一个该字串是否重复 ...
- BZOJ4598 [Sdoi2016]模式字符串 【点分治 + hash】
题目 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m 的模式串s,其中每一位仍然是A到z的大写字母.Alice希望知道,有多少对结点< ...
- 【基本算法入门-字符串哈希(Hash)】-C++
字符串哈希入门 说得通俗一点,字符串哈希实质上就是把每个不同的字符串转成不同的整数. 为什么会有这样的需要呢?很明显,存储一个超长的字符串和存储一个超大但是能存的下的整数,后者所占的空间会少的多,但主 ...
- 841. 字符串哈希(hash)
给定一个长度为n的字符串,再给定m个询问,每个询问包含四个整数l1,r1,l2,r2l1,r1,l2,r2,请你判断[l1,r1l1,r1]和[l2,r2l2,r2]这两个区间所包含的字符串子串是否完 ...
- Hash记录字符串
Hash记录字符串模板: mod常常取1e9+7,base常常取299,,127等等等....有的题目会卡Hash,因为可能会有两个不同的Hash但却有相通的Hash值...这个时候可以用双Hash来 ...
- 安全的字符串拷贝strcpy_s的实现与理解
在C标准库中提供了字符串拷贝函数strcpy,而微软则为为它提供了一个更安全的版本strcpy_s,其函数原型为 errno_t __cdecl strcpy_s( char* _Destinatio ...
- Ruby中的Hash(哈希),你可以理解为字典
原文链接 以下代码在Ruby 2.5.1中编译通过 定义 myHash = Hash.new myHash1 = Hash["key1" => 100, "key2 ...
随机推荐
- Codeforces 1060 F. Shrinking Tree
题目链接 一道思维好题啊...感觉这种类型的题很检验基本功是否扎实(像我这样的就挂了). 题意:你有一棵\(n\)个点的树,每次随机选择一条边,将这条边的两个端点合并,并随机继承两个点标号中的一个,问 ...
- Python定义函数
在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 我们以自定义一个求绝对值的my_abs函数 ...
- 【刷题】BZOJ 3930 [CQOI2015]选数
Description 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公 ...
- CF1088F Ehab and a weird weight formula 贪心 倍增
CF1088F Ehab and a weird weight formula 题意 给定一棵树,点有点权,其中这棵树满足除了权值最小的点外,每个点至少有一个点权小于它的相邻点. 要求你重新构建这棵树 ...
- BZOJ 2337 XOR和路径 | 高斯消元 期望 位运算
BZOJ 2337 XOR和路径 题解 这道题和游走那道题很像,但又不是完全相同. 因为异或,所以我们考虑拆位,分别考虑每一位: 设x[u]是从点u出发.到达点n时这一位异或和是1的概率. 对于所有这 ...
- 【bzoj4542】 Hnoi2016—大数
http://www.lydsy.com/JudgeOnline/problem.php?id=4542 (题目链接) 题意 给出一个素数$P$,一个数串$S$,$m$个询问,每次询问区间$[l,r] ...
- 安装logstash5.4.1,并使用grok表达式收集nginx日志
关于收集日志的方式,最简单性能最好的应该是修改nginx的日志存储格式为json,然后直接采集就可以了. 但是实际上会有一个问题,就是如果你之前有很多旧的日志需要全部导入elk上查看,这时就有两个问题 ...
- Kotlin入门简介
Kotlin的“简历” 来自于著名的IDE IntelliJ IDEA(Android Studio基于此开发) 软件开发公司 JetBrains(位于东欧捷克) 起源来自JetBrains的圣彼得堡 ...
- 解题:BZOJ 4644 经典砂比题(雾
题面 初见线段树分治 (对我来说可不是什么经典题=.=) 把时间轴建出来一棵线段树,然后在对应的区间上打标记,最后把整棵树DFS一遍,到叶节点输出答案即可 (把最终答案开成全局的了调了半天 #incl ...
- 【枚举&数据结构】【P2484】 [SDOI2011]打地鼠
Description 给定一个网格,每个格子上有一个数字.一次操作可以将 \(r~\times~c\) 的一块矩形的数字减去 \(1\).必须保证这个矩形中的数全部为正.每次操作的 \(r\) 和 ...