字符串哈希
简单说就是把一个字符串映射成一个数字
具体点,就是把一个字符串如”ABC”映射成一个p进制的数字
“ABC” –> p^2+A + p^1+B + p^0+C = 哈希值, 一般p取131或13331
本题需要求到一个字符串中任意两个区间的子串是否相同
可以转换为求两个区间子串的哈希值是否相等
思路:
用前缀和的思想,求出前缀字符串的哈希值
举例说明:
"ABCDEFGHI"
123456789 (下标)
L R
字符串"A"的 哈希值为 p^0+A
字符串"AB" 哈希值为 p^1+A + p^0+B
字符串"ABC" 哈希值为 p^2+A + p^1+B + C
字符串[1,L-1]的哈希值为 p^3+A + p^2+B + p^1+C + p^0+D
字符串[1,R] 的哈希值为 p^8+A + p^7+B + ... + P^0+I
那么如何求[L,R]字符串的哈希值呢,根据前缀和的思想,就是h[R] - h[L-1] (h[R]表示从[1,R]的字符串哈希值)
但是发现h[R]从[1,L-1]这一段left,每个数都比right这一段多乘了p^(R-(L-1))
所以字符串从[L,R]的哈希值为h[R] - h[L - 1] * p^(R-(L-1)) = h[R] - h[L - 1] * p^(R-L+1)
import java.io.*;
class Main{
static BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws Exception{
String[] s = read.readLine().split(" ");
int n = Integer.valueOf(s[0]);
int t = Integer.valueOf(s[1]);
String w = read.readLine();
int P = 131;
long[] h = new long[n + 10];
long[] p = new long[n + 10];
p[0] = 1;
for(int i = 1; i <= n; i++){
p[i] = p[i - 1] * P;
h[i] = h[i - 1] * P + w.charAt(i - 1);
}
while(t-- > 0){
s = read.readLine().split(" ");
int l1 = Integer.valueOf(s[0]); int r1 = Integer.valueOf(s[1]);
int l2 = Integer.valueOf(s[2]); int r2 = Integer.valueOf(s[3]);
String out = h[r1] - h[l1 - 1] * p[r1 - l1 + 1] == h[r2] - h[l2 - 1] * p[r2 - l2 + 1] ?
"Yes" : "No";
log.write(out + "\n");
}
log.flush();
}
}