对string进行hash算法:
https://blog.csdn.net/Mikchy/article/details/103995537
实质上就是对每个字符串找到唯一相对应的数字值。
假设字符串为s,则对应映射值idx(s[i])=s[i]-'a'+1** (这里a对应1)
整个字符串所有字串的哈希表:
(类似十进制的表示,14,一开始是 0,然后 0 * 10 + 1 = 1,接着 1*10 + 4 = 14)。
base是人为设定进制,随意>26,为降低冲突风险取133等数。
进行一系列优化之后得到比较好的公式:
例题1,自动溢出(不做取模运算)上面式子第一个内括号里的就是
实际使用上因为l-1可能为负数,所以进行加一处理类似这个样子:最好把r,l从一开始计数以免混乱
ull hash1 = hash[y1+1] - hash[x1] * p[y1 + 1 - x1];
#define ull unsigned long long // 自然溢出用 unsigned long long
class Solution {
public:
int distinctEchoSubstrings(string text) {
int num;// 子串满足条件的个数
int l ,r=0;
int n=text.size();
ull hash[n+1];
hash[0]=0;
ull base=29;
ull p[text.length()];
p[0]=1;
unordered_set<ull> H;
for(int j=1;j<text.length();j++){
p[j]=p[j-1]*base;
}
//首先转换整个字符串的哈希表,子串可以用主串的哈希表公式计算
for(int i=0;i<text.length();i++){
hash[i+1]=hash[i]*base+text[i]-'a'+1;
}//哈希表的大小要超过字符串一个,因为第一个下标0无用
//遍历所有字串
for(l=0;l<text.length();l++){
for(r=l+1;r<text.length();r++){
//求此时[l,r]串分开两半的哈希值
//子串长度只有偶数可以
if((l-r)%2!=0){
//分为[l,(r+l)/2]和[(r+l)/2+1,r]两部分并比较其哈希值
int x1,y1,x2,y2;
x1=l;
x2=(r+l)/2+1;
y1=(r+l)/2;
y2=r;
ull hash1 = hash[y1+1] - hash[x1] * p[y1 + 1 - x1];
ull hash2 = hash[y2+1] - hash[x2] * p[y2 + 1 - x2];
if(hash1==hash2){
H.insert(hash1);
}
}
}
}
num=H.size();
// cout<<num<<endl;
return num;
}
};
这道题我遍历子串的方式有点蠢,采用双伪指针的方式,看别人是用长度和坐标表示