题目链接
当出现地址冲突时,在数组下面开一个链。
单链表的模拟再复习一下,莫忘了
此外,对于数组大小N的选择,尽量选择质数,研究表明质数使得地址冲突产生的次数变少
int k=((x%N)+N)%N;
这里注意,是防止x为负数
#include
#includeusing namespace std;const int N=1e5+3;int h[N],e[N],ne[N],idx=0;
int n;void insert(int x){//将x插入哈希表int k=((x%N)+N)%N;++idx;e[idx]=x;ne[idx]=h[k];h[k]=idx;
}bool query(int x){int k=((x%N)+N)%N;for(int i=h[k];i!=-1;i=ne[i]){if(e[i]==x)return true;}return false;
}int main(){memset(h,-1,sizeof h);cin>>n;while(n--){string s;int x;cin>>s;if(s=="I"){cin>>x;insert(x);}else{cin>>x;if(query(x))cout<<"Yes"<
思路:
- 插入: 映射到k,发现如果被占了,那就从后看找到空的再插入
- 查找: 映射到k,一直往后找直到等于null。如果能找到就有,不能找到就没
使用find实现,find用于查找x所在的下标或者是要被插入的下标
#include
#includeusing namespace std;const int N=1e5+3,null=0x3f3f3f3f;int h[N];
int n;int find(int x){//对于x,找一下其在什么位置可以放置,如果没有返回0 int k=((x%N)+N)%N;while(h[k]!=null&&h[k]!=x){k++;if(k==N) k=0;}return k;
} int main(){memset(h,0x3f3f3f3f,sizeof h);cin>>n;while(n--){string s;int x;cin>>s;if(s=="I"){cin>>x;int k=find(x);h[k]=x;}else{cin>>x;if(h[find(x)]!=null)cout<<"Yes"<
题目链接
因为题目是判断区间内字符串是否相等,那么考虑类似的前缀和
定义
“abcdefg”
h[1]=“a”
h[2]=“ab”
h[3]=“abc”
对于每一个h[],我们都将其看作一个p进制数,
其中abc=(123)p
这样每个数都会对应一个值
在字符串哈希中,比较特殊的是,如果我们取P=131,那么发生地址冲突的概率仅为0.01%
因此这里我们就不考虑地址冲突
那么如果要求[L,R]区间内的字符串哈希值
那么就是:
然后其实我们都不用存,因为假设了哈希地址不冲突,直接每次求值即可。
#include
#includeusing namespace std;
const int N=1e5+10;//h用于存数,p用于存p的几进制
int h[N],p[N];
int P=131;int n,m;unsigned long long get(int l, int r){return h[r]-h[l-1]*p[r-l+1];
}int main(){cin>>n>>m;string s;cin>>s;p[0]=1;for(int i=1;i<=n;i++){h[i]=h[i-1]*P+s[i-1];p[i]=p[i-1]*P;}while(m--){int l1,l2,r1,r2;cin>>l1>>r1>>l2>>r2;if(get(l1,r1)==get(l2,r2))cout<<"Yes"<