哈希学习笔记

hash学习笔记

  1. 常用函数: $ hash[i] = \sum _{j=i} ^{len-1} {s[j]*X^{j-i}}, X ≥ |字符集| $ 取多个模,对于一个子串\(s[i]s[i+1]..s[j]\)\(hash = hash[i] - hash[j+1]*X^{j-i+1}\),预处理\(hash[i]\)以及\(X^i\)即可\(O(1)\)求出所有的子串hash值
  2. 一般运用hash进行快速查找,状态压缩,其他hash相关:康托展开及逆展开,ELFhash

Problem A

  1. 题意:给定一字符串S,询问\(LCP(x,y)\),即从x,y分别开始的最长公共前缀
  2. 做法:二分最长公共前缀的长度L,\(O(1)\)判断两个串的\(hash\)是否相同
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define frep(i,a,b) for(int i=a;i>=b;--i)
typedef unsigned long long ll;
const int N = 100007;
const ll base = 107;
using namespace std;
int n,q;
ll P[11][N], h[11][N], mod[11];
int cc;
char s[N];
void init_hash() {cc=0;mod[++cc] = 1e9+7;mod[++cc] = 1000007;mod[++cc] = 998244353;mod[++cc] = 100007;P[0][0]=1; rep(i,1,100) P[0][i]=P[0][i-1]*base;frep(i,n,1) h[0][i] = h[0][i+1]*base + s[i];rep(i,1,cc){P[i][0]=1;rep(j,1,100) P[i][j]=(P[i][j-1]*base)%mod[i];}rep(i,1,cc)frep(j,n,1)h[i][j] = ((h[i][j+1]*base)%mod[i]+s[j])%mod[i];
}
ll ask0(int x,int y) {if(x>y)swap(x,y);return h[0][x]-h[0][y+1]*P[0][y-x+1];
}
ll ask1(int x,int y,int z) {if(x>y)swap(x,y);return (h[z][x]%mod[z]-(h[z][y+1]*P[z][y-x+1])%mod[z]+mod[z])%mod[z];
}
int ck(int x,int y,int L) {if(ask0(x,x+L-1)!=ask0(y,y+L-1))return 0;rep(i,1,cc){if(ask1(x,x+L-1,i)!=ask1(y,y+L-1,i)) return 0;}return 1;
}
int solve(int x,int y) {int l=1,r=min(n-x+1,n-y+1),mid,ans=0;if(s[x]!=s[y])return 0;while(l<=r) {mid = (l+r)>>1;if(ck(x,y,mid))l=mid+1,ans=mid;else r=mid-1;}return ans;
}int main() {scanf(" %s",s+1);n=strlen(s+1);init_hash();scanf("%d",&q);while(q--) {int x,y;scanf("%d %d",&x,&y);printf("%d\n",solve(x,y));}return 0;
}

Problem B

  1. 题意:给定一字符串S,1)询问\(LCP(x,y)\),即从x,y分别开始的最长公共前缀;2)修改位置x的字符为y
  2. 做法1:线段树维护维护每个位置的hash[i],修改操作相当于给区间[1,x]加上
    \[(y-s[x])*X^x,(y-s[x])*X^x-1,...(y-s[x])*X^0\]
    这一等比数列,查询就是单点查询,再用上一题的做法即可。区间加公比固定的等比数列
  3. 做法2:线段树维护\(S[i]*X^i\)修改就是单点修改,查询\([i,j]\)区间和之后要除以\(X^i\),要预处理对应模数的逆元。代码回头补。

Problem C [BZOJ1014]

  1. 题意:给定一字符串S,1)询问\(LCP(x,y)\),即从x,y分别开始的最长公共前缀;2)修改位置x的字符为y;3)在S的第x个字符后添加一个字符
  2. 做法:splay每个节点维护size[i]:子树大小,hash[i]:以i为根节点的子树的hash值,\(hash[fa]=hash[lson]+s[fa]*X^{size[lson]}+hash[rson]*X^{size[lson]+1}\),对于查询,每次把一个后缀旋转到一颗子树上,子树的根节点的hash值就是答案,对于修改,直接修改从这个点到根的路径上的hash值,对于插入,直接splay插入更新size和hash。代码等到学splay专题的时候我再努力写吧。

Problem D [BZOJ3555]

  1. 题意:n个长度为L的互不相同的字符串,求有多少对字符串互相相似。相似:如果两个字符串恰好有一个字符不同,则他们相似。n≤30000,L≤200,|字符集|≤64
  2. 做法:预处理每个串前缀的hash值,枚举哪一位不同,排序计算贡献。关键是如何快速求出去除第i位的字符串的hash值。下面进行推导:
    对于字符串S, \(hash[i] = S[1]*X^{i-1} + S[2]*X^{i-2} + ... + S[i]\)
    除去S串的第\(x\)个字符的字符串\(Hash = (S[1]*X^{n-1} + S[2]*X^{n-2} + ... + S[x-1]*X^{n-x+1})+(S[x+1]*X^{n-x}+S[x+2]*X^{n-x-1}...+S[n])\\= hash[x-1]*X^{n-x+1} +(hash[n]-hash[x]*X^{n-x})\)
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define frep(i,a,b) for(int i=a;i>=b;--i)
typedef unsigned long long ll;
const int N = 50100;
const ll base = 107;
using namespace std;
int n,q,L,X;
ll P[211], h[N][211],a[N];
char s[211];
ll cal(int s,int x) {return h[s][x-1]*P[L-x+1] +(h[s][L]-h[s][x]*P[L-x]);
}
int main() {scanf("%d%d%d",&n,&L,&X);P[0]=1;rep(i,1,L)P[i]=P[i-1]*base;rep(i,1,n) {scanf(" %s",s+1);rep(j,1,L) h[i][j]=h[i][j-1]*base+s[j];}int ans=0;rep(i,1,L){rep(j,1,n)a[j]=cal(j,i);sort(a+1,a+n+1);int tmp = 0;rep(j,2,n){if(a[j]!=a[j-1])tmp=0;else ++tmp;ans += tmp;}}printf("%d\n",ans);return 0;
}

二维hash[BZOJ2462]

  1. 题意:给定一个M行N列的01矩阵,以及Q个A行B列的01矩阵,你需要求出这Q个矩阵哪些在
    原矩阵中出现过。所谓01矩阵,就是矩阵中所有元素不是0就是1。
  2. 做法:类似一维hash,先竖着hash,再横着hash,两次要用不同的base,查询子矩形方法类似于差分。
  3. hints:本题要对矩阵的hash值二次取mod,用map会tle
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
typedef unsigned long long ll;
const int N = 1007;
const ll base1 = 107;
const ll base2 = 31;
const ll mod = 10000007;
using namespace std;
int n,m,a,b,q;
ll P1[N], P2[N], h[N][N];
bool vis[mod+1];
char mp[N][N];
void init_hash() {P1[0]=1; rep(i,1,100) P1[i]=P1[i-1]*base1;P2[0]=1; rep(i,1,100) P2[i]=P2[i-1]*base2;rep(i,1,n)rep(j,1,m) h[i][j] += h[i-1][j]*base1 + mp[i][j];rep(i,1,n)rep(j,1,m) h[i][j] += h[i][j-1]*base2;
}
ll ask(int x,int y,int xl,int yl) {return h[x][y]-h[x-xl][y]*P1[xl]-h[x][y-yl]*P2[yl]+h[x-xl][y-yl]*P1[xl]*P2[yl];
}
int main() {scanf("%d%d%d%d",&n,&m,&a,&b);rep(i,1,n)scanf(" %s",mp[i]+1);init_hash();rep(i,a,n)rep(j,b,m) vis[ask(i,j,a,b)%mod]=1;scanf("%d",&q);while(q--) {rep(i,1,a)scanf(" %s",mp[i]+1);memset(h,0,sizeof(h));rep(i,1,a)rep(j,1,b)h[i][j]+=h[i-1][j]*base1+mp[i][j];rep(i,1,a)rep(j,1,b)h[i][j]+=h[i][j-1]*base2;printf("%d\n",vis[h[a][b]%mod]);}return 0;
}

转载于:https://www.cnblogs.com/RRRR-wys/p/9256622.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/320742.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Net Core集成Exceptionless分布式日志功能以及全局异常过滤

相信很多朋友都看过我的上篇关于Exceptionless的简单入门教程[asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程][https://www.cnblogs.com/yilezhu/p/9193723.html] 上篇文章只是简单的介绍了Exceptionless是什么&#xff1f;能做什么呢…

【斐波那契】【前缀和】无限序列

无限序列 题目大意&#xff1a; 有这样一个规则&#xff1a;1.把“1”变成“10” 2.把“0”变成“1” 一个序列的第一位是“1” 然后是&#xff1a;“10”&#xff0c;“101”…… 序列无限次操作后会得到“1011010110110101101……” 问某一个区间内有多少个“1” 原题&…

CF496E-Distributing Parts【平衡树,贪心】

正题 题目链接:https://www.luogu.com.cn/problem/CF496E 题目大意 nnn个[li,ri][l_i,r_i][li​,ri​]&#xff0c;mmm个[ai,bi,ki][a_i,b_i,k_i][ai​,bi​,ki​]表示可以覆盖掉kik_iki​个ai≤li≤ri≤bia_i\leq l_i\leq r_i\leq b_iai​≤li​≤ri​≤bi​的区间&#xff0…

kmp学习笔记

kmp&#xff0c;扩展 kmp 学习笔记 说再前边 字符串水平基本为0&#xff0c;学了第4遍KMP了&#xff0c;总是忘。。。网上资料很多&#xff0c;就不详细讲解了。抄的kuangbin神犇模板 kmp 一些知识 循环节大小&#xff1a;n - nxt[n]模板[HDU2087] 下标从0开始 nxt[i] 为满足p[…

AspNetCore微服务下的网关-Kong(一)

Kong是Mashape开源的高性能高可用API网关和API服务管理层。它基于OpenResty&#xff0c;进行API管理&#xff0c;并提供了插件实现API的AOP。Kong在Mashape 管理了超过15,000 个API&#xff0c;为200,000开发者提供了每月数十亿的请求支持。本文将从架构、API管理、插件三个层面…

【DP】删数

删数 题目大意&#xff1a; 有一堆数x1,x2……xnx_1,x_2……x_nx1​,x2​……xn​&#xff0c;可以从两边删除一些数删除i~k的价值是∣xi–xk∣∗(k−i1)|xi – xk|*(k-i1)∣xi–xk∣∗(k−i1)&#xff0c;求价值最大是多少 原题&#xff1a; 题目描述 有N个不同的正整数数…

CF396B-On Sum of Fractions【数学】

正题 题目链接:https://www.luogu.com.cn/problem/CF396B 题目大意 定义 v(n)v(n)v(n)表示≤n\leq n≤n的最大整数u(n)u(n)u(n)表示>n>n>n的最小整数 求∑i2n1v(i)u(i)\sum_{i2}^n\frac{1}{v(i)u(i)}i2∑n​v(i)u(i)1​ 解题思路 有式子b−aab1a−1b\frac{b-a}{ab…

拥抱开源, Office 365开发迎来新时代

这个话题我曾经写过文章&#xff0c;也在一些场合做过专题分享。今天换一种方式&#xff0c;你可以直接点击下面这个小程序&#xff0c;用十分钟左右的时间&#xff0c;听我再讲一讲吧。你需要在微信里面才能看到下面的小程序链接&#xff0c;并且可以直接点击你可以打开该文档…

Wannafly挑战赛19

Wannafly挑战赛19 A. 队列Q 需要支持把一个元素移到队首&#xff0c;把一个元素移到队尾&#xff0c;移到队首就直接放到队首前面那个位置&#xff0c;原位置标为0&#xff0c;队尾同理。 #include <bits/stdc.h> #define rep(i,a,b) for(int ia;i<b;i) typedef long …

【模拟】俄罗斯方块

俄罗斯方块 题目大意&#xff1a; 在俄罗斯方块中&#xff0c;放一块方块进一个图中&#xff0c;问刚好和上的可能性有多少种 原题&#xff1a; 题目描述 相信大家都玩过“俄罗斯方块”游戏吧&#xff0c;“俄罗斯方块”是一个有趣的电脑小游戏&#xff0c;现有一个有C列、…

实体类的动态生成(一)

前言在应用开发中&#xff0c;通常都会涉及各种 POJO/POCO 实体类&#xff08;DO, DTO, BO, VO&#xff09;的编写&#xff0c;有时这些实体类还需要实现 INotifyPropertyChanged 接口以支持属性变更通知&#xff0c;一般我们都会手写这些代码或者通过工具根据数据库表定义抑或…

CF525D-Arthur and Walls【贪心】

正题 题目链接:https://www.luogu.com.cn/problem/CF525D 题目大意 n∗mn*mn∗m的网格&#xff0c;有∗*∗和...&#xff0c;每次可以将∗*∗改成...。求最少操作使得每个...所在的联通块都是一个矩形。 解题思路 因为一个大矩形中每一个小块也是一个矩形&#xff0c;反之同理…

SoundHound Inc. Programming Contest 2018[C. Ordinary Beauty]

SoundHound Inc. Programming Contest 2018 -Masters Tournament-[C. Ordinary Beauty] 打表找规律的。 \(n 1\) 时&#xff0c; \(ans m\)\(n 2\) 时&#xff0c; \(ans 2*(m-1)*2^{m-2}\)\(n 3\) 时&#xff0c; 1) \(d 0, ~~ ans 3*(m-1)*3^{m-2}\) 2) \(d 1, ~~ an…

初一模拟赛总结(2019.6.1)

成绩&#xff1a; 注&#xff1a;rankrankrank是有算其他dalaodalaodalao的 rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3T4T4T4333hkyhkyhky360360360100100100606060100100100100100100444lyflyflyf320320320100100100202020100100100100100100555lthlthlth1…

实体类的动态生成(二)

前言实体类的动态生成&#xff08;一&#xff09;由于采用字典的方式来保存属性变更值的底层设计思想&#xff0c;导致了性能问题&#xff0c;虽然.NET的字典实现已经很高效了&#xff0c;但相对于直接读写字段的方式而言依然有巨大的性能差距&#xff0c;同时也会导致对属性的…

CF442C-Artem and Array【贪心】

正题 题目链接:https://www.luogu.com.cn/problem/CF442C 题目大意 nnn个数&#xff0c;删除一个数可以获得左右两边最小值的价值&#xff0c;求删除所有数的最大价值。 解题思路 对于一个位置如果它左右两边都比它高那么这个位置一定删除&#xff0c;然后序列会呈一个单峰状…

Codeforces 1005D Polycarp and Div 3

Codeforces 1005D Polycarp and Div 3 dp[i]表示前i个数最多能分成多少块%3为0&#xff0c;nxt[x]表示x这个上一次出现的位置。 首先想到 $ dp[i] max(dp[j]) 1, (sum[i]-sum[j]) mod 3 0$&#xff0c;然后注意到他一定是从最近的那个满足条件的位置&#xff0c;也就是nxt[i…

维修栅栏【DP】

维修栅栏 题目大意&#xff1a; 有一串数&#xff0c;要把这一串数改成全部非0的&#xff0c;每一次可以更改某一段的全部数字&#xff0c;但有代价sqrt(m)sqrt(m)sqrt(m)&#xff08;m为当前子串的长度&#xff09; 原题&#xff1a; 题目描述 农场的栅栏年久失修&#x…

hdu6356-Glad You Came【RMQ】

正题 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid6356 题目大意 nnn个数的一个序列aaa开始都是000。mmm个操作[li,ri,vi][l_i,r_i,v_i][li​,ri​,vi​]表示axmax{ax,v}(li≤x≤ri)a_xmax\{a_x,v\}(l_i\leq x\leq r_i)ax​max{ax​,v}(li​≤x≤ri​)&#xff0c;求…

2015 German Collegiate Programming Contest (GCPC 15)

2015 German Collegiate Programming Contest (GCPC 15) B. Bounty Hunter II 给定一张DAG&#xff0c;求一种方案&#xff1a;用最少的路径将所有点覆盖。写了按长度贪心&#xff0c;按出度的贪心。。。果断挂了。下来搜了下题解&#xff0c;看到了二分图。就懂了。。。把点拆…