字符串哈希匹配字符串

字符串哈希匹配字符串

问题描述

这是一道模板题。

给定一个长度为 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;
    }
}
相关推荐
BadBadBad__AK43 分钟前
线段树维护区间 k 次方和
c++·数学·算法·stl
_清歌13 小时前
DSpark 深度解读:DeepSeek-V4 如何用「半自回归」把推理速度提升 85%
算法
统计实现局13 小时前
SVD 的三步走:双对角化、Givens 收敛、排序
算法
躬行见万象13 小时前
《VLA 系列》UniLab 强化训练 | G1 机器人 |复现
算法
统计实现局13 小时前
对称不定分解(Bunch-Kaufman):为什么 Cholesky 不够用
算法
统计实现局13 小时前
dqrsl 拆解:拿着 QR 结果能算出哪 5 种东西
算法
统计实现局13 小时前
为什么 Cholesky 求逆比 Gauss-Jordan 快一倍——行列式溢出防护详
算法
To_OC1 天前
LC 994 腐烂的橘子:人人都说是 BFS 入门题,我却写了三遍才过
javascript·算法·leetcode
金銀銅鐵1 天前
[Python] 扩展欧几里得算法
python·数学·算法