import java.util.Scanner;
public class A025_字符串匹配_RabinKarp {
private static int seed;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.next();
String s = sc.next();
seed = s.length();
long k = work(s, 0, s.length());
long t = work(str, 0, s.length());
int i = s.length();
while (i < str.length()) {
if (t == k) {
System.out.println(i - s.length() + " ");
}
char cur = str.charAt(i);
char pre = str.charAt(i - s.length());
t = (long) (t * seed + cur - Math.pow(seed, s.length()) * pre);
i++;
}
if (t == k) {
System.out.println(i - s.length() + " ");
}
}
public static long work(String str, int i, int len) {
long sum = 0;
for (; i < len; i++) {
sum = sum * seed + str.charAt(i);
}
return sum;
}
}
这个方法是用滚动hash来做的
- 首先是进行两个预处理,原字符串的hash值k和首次几个长度的hash值t,t每次都会及进行变化
- 求一段长度的hash:sum = sum * seed + str.charAt(i);可以参考下图👇
1、这是如何进行滚动求值
t = (long) (t * seed + cur - Math.pow(seed, s.length()) * pre);
2、也就是先把当前元素,加入到整体数值中👇
t * seed + cur
3、然后再算出长度的前一个值👇
Math.pow(seed, s.length()) * pre
这里为什么要对seed求一个次方呢,是因为要从原数值中减去,而在2中,可以看到,t又成了一次seed,所以这里求得seed的次方,不用进行-1;