使用一个与字符串 等长的哈希数组 h[],以及次方数组p[] 。
由字符串预处理得到这样的哈希数组和次方数组复杂度为 O(n)。当我们需要计算子串s[i...j]的哈希值,只需要利用前缀和思想h[j]-h[i-1]*p[j-i+1] 即可在O(1) 时间内得出哈希值(与子串长度无关)。
class Solution {
int N = (int)1e5+10, P = 131313;
//经验值
int[] h = new int[N], p = new int[N];//创建哈希数组和次方数组
public List<String> findRepeatedDnaSequences(String s) {//集合数组
int n = s.length();//字符串长度
List<String> ans = new ArrayList<>();//字符串ans的创建
p[0] = 1;
for (int i = 1; i <= n; i++) {
h[i] = h[i - 1] * P + s.charAt(i - 1);
p[i] = p[i - 1] * P; //预处理前缀的哈希值
}
Map<Integer, Integer> map = new HashMap<>();//创建哈希表
for (int i = 1; i + 10 - 1 <= n; i++) {
int j = i + 10 - 1;
int hash = h[j] - h[i - 1] * p[j - i + 1];//利用前缀和处理
int cnt = map.getOrDefault(hash, 0);
if (cnt == 1) ans.add(s.substring(i - 1, i + 10 - 1));
map.put(hash, cnt + 1);
}
return ans;
}
}