标签:长度 题目 pre 超过 序列 lan htm 哈希 wap
DAY 3
数据结构
1.堆
Priority_queue 大根堆
Priority_queue<int , vector<int> , greater<int> > 小根堆
支持插入一个值,删除最大/最小值
它重载了运算符或函数类
2.LCA(最近公共祖先)
局限于树,倍增大法好
我们有一棵树,定义某个点的祖先为这个点到根节点的路径上的所有点
对于点A,B,他们会有一些公共祖先
一旦找到LCA,他们的所有公共祖先都可找到,LCA一定是最深的公共祖先
用途:找任意两点的最短路,AàLCA + BàLCA
步骤:
If( depA<depB) swap(A,B)
2. 把A,B调到同一深度
3. A,B同时上调直到A=B,找到LCA
复杂度是O(dep)的,但是如果你的树是一条链,那么还不如不用
考虑优化
P[x][i],x的向上第2^i 个祖先
P[x][i]= P[P[x][i-1]][i-1]
(1) 优化:把A,B调到同一深度
我们发现A和B之间有深度差
比如 d[A]-d[B]=19
二级制分解19
19=10011
AàP[A][4] 16
AàP[A][1] 2
AàP[A][0] 1
(2) 优化:A,B同时上调
一开始A,B的祖先一直不一样,直到某个点,往后一样了就都一样了
我们不好确定最早的相同祖先的点,但是我们可以找到最后2个不相同祖先的x,y,那么此时,他们的父亲就会是LCA
For(i=16~0)
If(f[A][i]!=f[B][i])
A,B同时上跳2^i
复杂度O(logn)
LCA应用:
处理树上可以差分的信息
用到树上求A到B的最短路径:Aàgen + Bàgen - 2*LCAàgen
3.ST 表
只查询区间最大最小值,不修改,静态的
定义mx[i][j] 是 iài + 2^j -1 的最大值
如果要求区间[L,R]的最大值
比如区间 [19 46]
先求区间长度 46-19+1=28
发现它可以被两个16覆盖
PS:求区间最大值重叠不影响
覆盖区间长P=Floor(log2(L))
把[L,R]拆成两个区间 [L,P]和[R-2^P,R],分成两半分别处理
比如递归求解max
st[i][j] = max(st[i][j-1], st[i + (1 << j-1)][j-1])
4.HASH
是一种函数
平时说的HASH就是:设计一个函数F(字符串) à int ,就是把字符串变成数字,
map 基于比较函数的红黑树
如果你在map中放字符串,两个字符串比较的复杂度O(字符串长度)
所以要开发一种新的方法
假设给你一个字符串 ababb,1表示a,0表示b
10100
ababb
回忆初学二进制,用类似的方法计算出一个值
b*2^0+b*2^1+a*2^2+b*2^3+a*2^4
HASH允许冲突,我们要尽量避免冲突,而不是根治冲突
给你一个乱码 yy1926
我们现在构造HASH
先确定几进制 P ,一个大质数,比字符串集大
那么计算它的值就是 6*p^0+2*p^1+9*p^2+1*p^3+y*p^4+y*p^5
前面数字还好啊,直接int计算了,那么对于字符呢??
取其ASCII码,mod 998244353 (一个大质数)
不过为了方便,可以直接开unsigned ll
Unsigned ll范围 0 ~ 2^64 -1
你惊奇的发现2^64 -1是个质数
允许自然溢出,自然溢出相当于取模
用Unsigned ll存,用它计算,省去取模操作
为了避免冲突,你还可以取模两个数
HASH如何计算子串的hash?
希望设计一种算法,至少满足字符串拼接删除
比如现在有字符串 damengshen 和一个 p
d d
di d*p^1+i
din d*p^2+i*p^1+n
ding d*p^3+i*p^2+n*p^1+g
如果要求
ing的hash就是hash[ding]- hash[d]*p^3
ng的hash就是hash[ding]- hash[d]*p^2
我们维护了字符串每个前缀的hash值
发现p的指数难以确定,其实p的指数就是差的字符串的长度
令h[i]表示1~i的hash值
h[i]=h[i-1]*p+s[i]
hash[i][j]=h[j] - h[i-1]*p^(j-i+1)
5.并查集
没有必要保留树的结构,所以一个点的父亲可以直接指向它的代表源
路径压缩
Father[x]à代表源
6.树状数组
int lowbit(int x){ return x&(-x); } void modify(int x,int y){ // add y to a[x] for(int i=x;i<=n;i+=lowbit(i)) c[i]+=y; } int query(int x){ // sum of a[1]...a[x] int ret=0; for(int i=x;i;i-=lowbit(i)) ret+=c[i]; return ret; } int query(int l,int r){ return query(r)-query(l-1); }
7.线段树
例题:
对于给出的一个数列
我们维护两个堆
大根堆堆顶维护中位数
考虑每次放两个数字进堆,比大根堆堆顶小的留在堆里,大的放到小根堆
一旦堆爆了,就把大根堆堆顶放到小根堆里啊
K叉哈夫曼树
用堆维护
你考虑把所有点取出来,与周围点连边,边权就是这两点海拔高度差,然后考虑排个序
单独去除边,不连边,然后一个一个往里边加入边,合并两个点为一个集合,当有一个集合的边数>=T,就确定了整个集合的等级
5.P5043 【模板】树同构([BJOI2015]树的同构)
对于每个点为根,求哈希
如果两个哈希集合相同,那么他们同构
标签:长度 题目 pre 超过 序列 lan htm 哈希 wap
原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/11191047.html