1 条题解
-
0
题目分析
我们需要处理一个长度最大为 的字符串,并计算其哈希值。为了减少哈希冲突和计算量,我们可以将字符串视为一个 进制的数字,其中 是字符集的大小(即不同字符的数量)。每个字符的权值由其首次出现的顺序决定。
解题思路
-
字符权值分配:
- 遍历字符串,记录每个字符首次出现的位置,按顺序分配权值(从 到 )。
- 例如,字符串
"abac"
的字符权值为a:0, b:1, c:2
,。
-
计算哈希值:
- 将字符串视为一个 进制的数,每个字符的权值作为该位的数字。
- 哈希值计算公式为: [ hash = \sum_{i=0}^{n-1} (val(s[i]) \times nc^{n-1-i}) \mod MOD ] 其中 是字符 的权值, 是一个大质数(如 )。
-
哈希表存储:
- 使用哈希表(如
unordered_map
)存储计算出的哈希值,避免重复计算。
- 使用哈希表(如
关键优化
- 避免大数溢出:
- 在计算过程中每一步都取模,防止数值溢出。
- 预处理幂次:
- 预处理 的幂次数组 ,加速计算。
复杂度分析
- 时间复杂度:
- 遍历字符串计算权值:。
- 计算哈希值:。
- 空间复杂度:
- 存储字符权值和幂次数组:。
代码实现
#include<iostream> #include<string> #include<cstdio> using namespace std; const int q=10000007; string str; int h[q]; int b[500]; int main() { int t,e,n,nc,k=0,ans=0; scanf("%d%d",&n,&nc); cin>>str; for (int i=0;i<str.length();i++) { if (b[str[i]]==0) b[str[i]]=++k; if (k==nc) break; } for (int i=0;i<str.length()-n+1;i++) { t=0; for (int j=i;j<i+n;j++) t=(t*nc+b[str[j]])% q; if (h[t]==0) { h[t]=1; ans++; } } printf("%d",ans); return(0); }
-
- 1
信息
- ID
- 201
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者