字符串哈希

字符串哈希

问题描述

将字符串映射为整数,使得:

  1. 相同的字符串映射到相同的整数
  2. 不同的字符串尽量映射到不同的整数
  3. 能够快速计算子串的哈希值

字符串哈希算法

算法思想

  1. 选择一个大质数作为模数
  2. 选择一个进制数 (通常为131或13331)
  3. 将字符串看作 进制数,对 取模
  4. 使用前缀和思想预处理子串哈希值

时间复杂度

  • 预处理时间:
  • 查询时间:
  • 空间复杂度:

代码实现

class StringHash {
private:
    const int P = 131;
    const long long M = 1e9 + 7;
    vector<long long> h, p;
    
public:
    StringHash(string& s) {
        int n = s.length();
        h.resize(n + 1);
        p.resize(n + 1);
        
        // 初始化次方数组
        p[0] = 1;
        for (int i = 1; i <= n; i++) {
            p[i] = (p[i-1] * P) % M;
        }
        
        // 计算前缀哈希
        h[0] = 0;
        for (int i = 1; i <= n; i++) {
            h[i] = (h[i-1] * P + s[i-1]) % M;
        }
    }
    
    // 计算子串[l,r)的哈希值
    long long getSubstringHash(int l, int r) {
        return ((h[r] - h[l] * p[r-l]) % M + M) % M;
    }
};
class StringHash {
    private final int P = 131;
    private final long M = 1000000007;
    private long[] h, p;
    
    public StringHash(String s) {
        int n = s.length();
        h = new long[n + 1];
        p = new long[n + 1];
        
        // 初始化次方数组
        p[0] = 1;
        for (int i = 1; i <= n; i++) {
            p[i] = (p[i-1] * P) % M;
        }
        
        // 计算前缀哈希
        h[0] = 0;
        for (int i = 1; i <= n; i++) {
            h[i] = (h[i-1] * P + s.charAt(i-1)) % M;
        }
    }
    
    // 计算子串[l,r)的哈希值
    public long getSubstringHash(int l, int r) {
        return ((h[r] - h[l] * p[r-l]) % M + M) % M;
    }
}
class StringHash:
    def __init__(self, s: str):
        self.P = 131
        self.M = 10**9 + 7
        n = len(s)
        
        # 初始化次方数组
        self.p = [0] * (n + 1)
        self.p[0] = 1
        for i in range(1, n + 1):
            self.p[i] = (self.p[i-1] * self.P) % self.M
        
        # 计算前缀哈希
        self.h = [0] * (n + 1)
        for i in range(1, n + 1):
            self.h[i] = (self.h[i-1] * self.P + ord(s[i-1])) % self.M
    
    # 计算子串[l,r)的哈希值
    def getSubstringHash(self, l: int, r: int) -> int:
        return ((self.h[r] - self.h[l] * self.p[r-l]) % self.M + self.M) % self.M

双哈希

为了降低哈希冲突的概率,可以使用两个不同的哈希函数:

  1. 选择两组不同的
  2. 同时计算两个哈希值
  3. 只有两个哈希值都相同时才认为字符串相同

应用场景

  1. 快速判断子串是否相同
  2. 字符串去重
  3. 最长回文子串
  4. 重复子串检测
  5. 字符串匹配

注意事项

  1. 选择合适的模数和进制
  2. 处理整数溢出
  3. 哈希冲突的处理
  4. 空串的处理
  5. 字符串长度的限制
牛客代码笔记-牛栋 文章被收录于专栏

汗牛充栋,学海无涯。<br/> 内含算法知识点讲解,以及牛客题库精选例题。<br/> 学习算法,从牛栋开始。

全部评论

相关推荐

09-21 21:14
门头沟学院
否极泰来来来来:和他说:这里不好骂你,我们加个微信聊
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务