【LeetCode】5994. 查找给定哈希值的子串

 1 class Solution {
 2 public:
 3     string subStrHash(string s, int p, int m, int k, int hash) {
 4         int n = s.size();
 5         unsigned long long pow[20010];  //long long防止溢出
 6         pow[0] = 1;
 7         for (int i = 1; i <= k; ++i) {
 8             pow[i] = (pow[i - 1] * p) % m;  //提前计算power的k次幂
 9         }
10         
11         for(int i=0;i<n;++i)   //初始化字母代表的数值,方便代码书写
12         {
13             s[i]-='a'-1;
14         }
15 
16         int ans;
17         unsigned long long sum=0;
18 
19         for(int j=0; j<k ; ++j)   //对第一个窗口n-k~n-1进行特殊判断
20         {
21             sum=(sum+(s[n-k+j])*pow[j]) % m;
22         }
23         if(sum==hash)
24         {
25             ans=n-k;
26         }
27 
28         for (int i = n-k-1 ; i >=0 ; i--)  //滑动窗口
29         {
30             sum=(sum*p-((s[i+k])*pow[k])%m+s[i]+m)%m;   //加m以防止变为负数
31             if(sum==hash)
32             {
33                 ans=i;
34             }
35         }
36 
37         string b;
38         for(int j=0;j<k;++j)
39         {
40             b+=(s[ans+j]+('a'-1)); //还原结果,加上'a'-1
41         }
42 
43         return b;
44     }
45 };

思路基本写在注释里了。

观察题意,因为解的结构的相似性,所以很容易联想到滑动窗口算法;但是由于除法不满足取模公式,所以这个滑动窗口需要倒着滑。

首先构造初始窗口,再用循环依次滑到最开始,因为要求最先出现的子串,所以得遍历一遍字符串。

代码中做了存储幂结果的优化,以及使用long long防止溢出。

posted @ 2022-01-30 16:02  Jerry2km1  阅读(85)  评论(0)    收藏  举报