作用:
通过预处理字符串,可将求出一个字符串的子串,并与其他字符串比较是否相同的,时间复杂度变为n(1)。
核心思想:
将字符串视为多项式。核心公式如下:
对于如何求一个字符串s内的子串(s[l:r])hash值。核心公式如下:
证明:
要消除 pre_hash[l] 对 pre_hash[r] 的影响为了只保留 s[l:r] 的哈希值,需要:
将 pre_hash[l] 左移 (r-l) 位(即乘以 B^(r-l))从 pre_hash[r] 中减去这个值。
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 1e9+7,B = 233;
string s;
void string_hash(){
cin>>s;
int n = s.size();
// pre_hash[i] 字符串s[:i-1]的hash值
// powb[i]: B的i次幂
vector<long long> pre_hash(n+1),powb(n+1);
powb[0] = 1;
for (int i=1;i<=n;i++){
pre_hash[i] = (pre_hash[i-1]*B+s[i-1])%MOD;
powb[i] = powb[i-1]*B%MOD;
}
// 字符串s[i:j]的hash值,这里把字符串的下标看作从1开始,比较清晰
for (int j=1;j<=n;j++){
for (int i=1;i<=j;i++){
cout<<(pre_hash[j]-pre_hash[i-1]*powb[j-i]%MOD+MOD)%MOD<<endl;
}
}
}
int main(){
// 关闭输入输出流同步
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 不使用科学计数法
// cout<<fixed;
// 中间填保留几位小数,不填默认
// cout.precision();
string_hash();
}