哈希-数组
数值
1.拉链法
--注意
1。取模取成最小的质数-判断条件
* int j =100001;
* int m=0;
* while (m<1){
* if(panduan(j)){
* m++;
* System.out.println(j);
* j++;
* }else {j++;}
*
* }
* 2。每个链表的0不存放值,作为结束点条件
* static int index=1;
* 3。输出的时候按照链表的形式输出
* int k = (x%N+N)%N;
* for(int i=h[k];i!=0;i=next[i]){
* if(e[i] == x)return true;
* }
* return false;
*/
package 大学菜;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
/*
* */
public class 哈希表拉链法2 {
//判断质数
static int N = 100003;
static int[] h = new int[N];
static int[] next = new int[N];
static int[] e = new int[N];
static int index=1;//为了保证头节点指向是0。
public static void insert(int x){
//取模
int k = (x % N + N) % N;
//找位置
e[index] = x;//先放好值,值和位置是两个不同的概念
next[index] = h[k];//这个地方找的是位置
h[k] = index;
index++;
}
public static boolean query(int x){
//Q x,询问数 x 是否在集合中出现过;
//先找位置
int k = (x%N+N)%N;
for(int i=h[k];i!=0;i=next[i]){
if(e[i] == x)return true;
}
return false;
}
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.valueOf(reader.readLine());
while (n-->0){
String[] s = reader.readLine().split(" ");
String action = s[0];
if(action.equals("I")){
int x = Integer.valueOf(s[1]);
insert(x);
}else {
int x = Integer.valueOf(s[1]);
if(query(x)){System.out.println("Yes");}
else {System.out.println("No");}
}
}
}
}
开放寻址法
注意:
/*开放寻址法
1.模数的寻找同拉链法。
2.数组范围定成原定要求的2-3倍
* 2。k个查找-如果有一直往后查找
* 1。添加
* 2。查找
* 3。删除-打标记进行删除-类似于查找的特殊
* */
package 大学菜;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class 哈希表开放寻址法2 {
//1.开辟空间大
static int N = 2000003;
static int[] h = new int[N];
//定一个超大值,开始的时候让他们都等于这个值
static int ull = (int)(1e9+1);
public static void insert(int x){
//模求地址
int k = (x%N+N)%N;
//冲突情况:当前位置不为空,并且不为x
while(h[k] != ull && h[k] != x){//位置不空,且x不存在
k ++;
if(k == N) k = 0; //末尾,从头开始
}
h[k] = x;
}
public static boolean query(int x){
int k= (x%N+N)%N;
while (h[k]!=ull){
if(h[k] == x){
return true;
}else {
k++;
if( k==N) k=0;
}
}
return false;
}
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.valueOf(reader.readLine());
for(int i=0 ;i<N;i++){
h[i] = ull;
}
while (n-->0){
String[] s = reader.readLine().split(" ");
String action = s[0];
if(action.equals("I")){
int x = Integer.valueOf(s[1]);
insert(x);
}else {
int x = Integer.valueOf(s[1]);
if(query(x)){System.out.println("Yes");}
else {System.out.println("No");}
}
}
}
}
字符串
字符串哈希值时。
使用进制的概念
字符串哈希(步骤):
1. 先将原字符串的所有前缀的哈希求出 (h[i] = h[i - 1] * P + str[i])
2. 用对应的公式求出对应区间的哈希值是否一样—> 区间[l,r]中的哈希值为:h[r]-h[l-1]*p[r-l+1]
3. 每次都要对h数组取模(%Q)
代码:
package 大学菜;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
/*
1.进制P=131
2.哈希值公式:h[i] = h[i-1] * P + str[i]
3.字符串区间公式是否相同公式: h[r] - h[l-1]*p[r-l+1]**/
public class 哈希字符串2 {
static int P = 131;
static int N =100010;
static long[] p = new long[N];
static long[] h = new long[N];
public static long get(int l,int r){
return h[r]-h[l-1]*p[r-l+1];
}
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String[] s = reader.readLine().split(" ");
int n = Integer.valueOf(s[0]);
int m = Integer.valueOf(s[1]);
p[0] = 1;//防止数据出现全0
String str = reader.readLine();
for(int i=1;i<=n;i++){
p[i] = p[i-1]*P;//数组保存的是每个不同的进制数
h[i] = h[i-1]*P + str.charAt(i-1);//每位不同的哈希值
}
//判断
while (m-->0){
String[] str2 = reader.readLine().split(" ");
int l1 = Integer.valueOf(str2[0]);
int r1 = Integer.valueOf(str2[1]);
int l2 = Integer.valueOf(str2[2]);
int r2 = Integer.valueOf(str2[3]);
//判断是否哈希值相同
if (get(l1,r1) == get(l2,r2)){
System.out.println("Yes");
}else {System.out.println("No");}
}
}
}