字符串哈希匹配字符串
问题描述
这是一道模板题。
给定一个长度为 nn 仅由小写字母构成的字符串 SS,再给定 qq 组查询,每次查询给定 44 个整数 l1,r1,l2,r2l1,r1,l2,r2。你需要输出 Sl1∼r1Sl1∼r1 与 Sl2∼r2Sl2∼r2 是否相同。
输入格式
第一行输入两个正整数 n,qn,q。(1≤n,q≤2×105)(1≤n,q≤2×105)。
第二行输入一个字符串 SS。((a ≤Si≤≤Si≤ z,1≤i≤n),1≤i≤n)。
接下来 qq 行每行输入 44 个正整数 l1,r1,l2,r2l1,r1,l2,r2。(1≤l1≤r1≤n,1≤l2≤r2≤n,r1−l1=r2−l2)(1≤l1≤r1≤n,1≤l2≤r2≤n,r1−l1=r2−l2)。
输出格式
输出 qq 行,对于每次查询,如果查询的两个字符串相同输出 Yes,否则输出 No。
样例输入
4 3
abbc
1 2 2 3
2 2 3 3
1 3 2 4
样例输出
No
Yes
No
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N = 2*100010,p=131;//改值减少冲突
static int a[]=new int[N];
static int b[]=new int[N];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// int n=Integer.parseInt(br.readLine());
String g[] = br.readLine().split(" ");
int n=Integer.parseInt(g[0]),q=Integer.parseInt(g[1]);
String string=br.readLine();
// h[i]=h[i−1]×p+s[i], h[0]=0
// p:基数(通常取质数,如 (131、13331))
// (s[i]):字符串第 i 位字符的 ASCII 值(示例中 A=65,B=66,C=67)
// h[l,r]=h[r]−h[l−1]×p^(r−l+1)
b[0]=1;
for (int i = 1; i <= n; i++) {
b[i]=b[i-1]*p;
a[i]=a[i-1]*p+string.charAt(i-1);
}
for (int i = 0; i <q; i++) {
g = br.readLine().split(" ");
int l1=Integer.parseInt(g[0]),r1=Integer.parseInt(g[1]);
int l2=Integer.parseInt(g[2]),r2=Integer.parseInt(g[3]);
if(getHash(l1, r1,string)==getHash(l2, r2,string)){
System.out.println("Yes");
}else{
System.out.println("No");
}
}
}
static int getHash(int l,int r,String string){
return a[r]-a[l-1]*b[r-l+1];
}
}
双哈希:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N = 2*100010,p1=131,p2=13331,mod1=(int)(1e9)+7,mod2=(int)(1e9)+9;//改p值减少冲突
static long a1[]=new long[N];//采用long
static long b1[]=new long[N];
static long a2[]=new long[N];
static long b2[]=new long[N];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// int n=Integer.parseInt(br.readLine());
String g[] = br.readLine().split(" ");
int n=Integer.parseInt(g[0]),q=Integer.parseInt(g[1]);
String string=br.readLine();
// h[i]=h[i−1]×p+s[i], h[0]=0
// p:基数(通常取质数,如 (131、13331))
// (s[i]):字符串第 i 位字符的 ASCII 值(示例中 A=65,B=66,C=67)
// h[l,r]=h[r]−h[l−1]×p^(r−l+1)
b1[0]=1;
for (int i = 1; i <= n; i++) {
b1[i]=b1[i-1]*p1%mod1;
a1[i]=(a1[i-1]*p1+string.charAt(i-1))%mod1;
}
b2[0]=1;
for (int i = 1; i <= n; i++) {
b2[i]=b2[i-1]*p2%mod2;
a2[i]=(a2[i-1]*p2+string.charAt(i-1))%mod2;
}
for (int i = 0; i <q; i++) {
g = br.readLine().split(" ");
int l1=Integer.parseInt(g[0]),r1=Integer.parseInt(g[1]);
int l2=Integer.parseInt(g[2]),r2=Integer.parseInt(g[3]);
if(getHash1(l1, r1,string)==getHash1(l2, r2,string) &&
getHash2(l1, r1,string)==getHash2(l2, r2,string)
){
System.out.println("Yes");
}else{
System.out.println("No");
}
}
}
static int getHash1(int l,int r,String string){
return (int)((a1[r]-a1[l-1]*b1[r-l+1])%mod1+mod1)%mod1;
}
static int getHash2(int l,int r,String string){
return (int)((a2[r]-a2[l-1]*b2[r-l+1])%mod2+mod2)%mod2;
}
}