作用:把一个庞大的 复杂的 映射到 一个较小的(0~n)//类似:离散化《特殊的哈希方式》(保序)(离散化后的数 相对位置保持不变)
思想:利用一个P进制的数 来表示字符串
时间复杂度:O(1)
功能:
1.添加
2.查找
3.删除:不为真的删除 而是在原链表上打上一个标记(bool变量/开一个数组) 记作删除
实现操作:
1.取模(一般取质数,离2的整次幂 尽可能远(这样冲突会减少))
2.处理冲突
存储结构:(处理冲突)
1.开放寻址法:构建一个一维数组(大小为题目的2~3倍 且为质数)将其映射在这个数组中 形象比喻:数组中有很多坑位 一个坑被占了 就会看下一个坑 直到找到空坑为止
const int N=2e5+3,null=0x3f3f3f;
int find(int x)
{
int t=(x%N+N)%N;
while(h[t]!=null&&h[t]!=x)
{
t++;
if(t==N) t=0;//从头开始找
}
return t;//返回这个空坑位
}
int main()
{
memset(h,0x3f,sizeof h);//解释 memset 是对单字节 赋值 而int是4个字节 故这样表示
。。。。
insert:
{
int k=find(x);
h[k]=x;
}
}
2.拉链法:构建一个一维数组(大小正常 符合题目 且为质数) 将其映射在这个数组中 形象比喻:数组有很多个槽位 庞大的映射到对应槽位 形成一条类似拉链的(拉链即单链表)
const int N=1e5+3;//质数
int e[N],ne[N],h[N],idx;
void insert(int x)
{
int k=(x%N+N)%N;//注意:确保返回为正数(x%N+N 这样N负的很大的时候 依旧可以)
e[idx]=x;
ne[idx]=h[k];//h[?]代表 第?个节点的头部指向位置
h[k]=idx++;//更新
}
bool find(int x)
{
int k=(x%N+N)%N;
for(int i=h[k];i!=-1;i=ne[i])
{
if(e[i]==x) return ture;
}
return false;
}
int main()
{
memset(h,-1,sizeof h);//先赋初值
}
字符串哈希方式:
(字符串前缀哈希法):解决字符串问题的利器 快速判断两个字符串是否相等
:把任何一个 字符串 映射到0~Q-1的一个数
1.把字符串看作一个 P进制的数
2.将 P进制的数 转化为 10进制的数(第一个数 乘P的n-1次 ;第二个数 乘P的n-2次 ;以此类推)
3.将 该数 模上一个Q(较小的数)
注意:1.任何一个字母 不能映射为数字0;
2.经验值:一般不存在任何冲突 :取P=131 或13331;Q取2^64(取unsigned long long
不取模);
公式:
h[R]-h[L]*P^(R-L+1);//从L到R的hash值