字符串哈希学习
h[i] = h[i-1] * p + s[i];
p[i] = p[i - 1] * p;
hashNum = h[i + len] - h[i] * p[len];
可以用字符串哈希来写
-
且仅当两个哈希值溢出程度与 Integer.MAX_VALUE 呈不同的倍数关系时,会产生错误结果(哈希冲突),此时考虑修改 或者采用表示范围更大的 long 来代替 int。
-
int做乘法发生溢出警告,可以 * 1ll 转换成 足够大的long long 来完成乘法操作,然后强行向下转换int
-
long long做乘法发生溢出警告,可以转换成足够大的__int128 来完成乘法操作,然后强行向下转换long long
-
mp.clear();减少哈希冲突
C++ 代码如下
class Solution {
// 且仅当两个哈希值溢出程度与 Integer.MAX_VALUE 呈不同的倍数关系时,会产生错误结果(哈希冲突),此时考虑修改 或者采用表示范围更大的 long 来代替 int。
// int做乘法发生溢出警告,可以 * 1ll 转换成 足够大的long long 来完成乘法操作,然后强行向下转换int
//131 4999 2011
public:
long long P = 131313,sz;
long long h[30010],p[30010];
unordered_map<long long,int> mp;
void pre(string & s){
h[0] = p[0] = 1;
for(int i = 1; i <= sz; ++i){
h[i] = ( __int128) h[i- 1] * P + s[i - 1];
p[i] = ( __int128) p[i - 1] * P;
}
}
long long get(int i,int len){
return h[i + len] - ( __int128)h[i] * p[len];
}
string longestDupSubstring(string s) {
sz = s.size();
pre(s);
string ans = "",y;
int l = 1,r = sz - 1,m;
while(l <= r){
mp.clear();//记得clear减少哈希冲突
bool f = false;
m = (l + r) >> 1;
for(int i = 0; i <= sz - m; ++i){
long long x = get(i,m);
if(mp.count(x)){
f = true;
ans = s.substr(i, m);
break;
}else ++mp[x];
}
if(f)
l = m + 1;
else r = m - 1;
}
return ans;
}
};