从0开始学算法——第十三天(Rabin-Karp 算法练习)

写在开头的话

学习了今天的基础知识,让我们来做几道题来练练手吧。(题目是别的地方扒来的,参考答案是我自己写的,肯定不是最优解,有更好的方法欢迎评论区交流)

第一题------字符串哈希匹配字符串(模板题)

第二题------字符串哈希匹配字符串(模板题)

参考答案

第一题参考答案(Python版)

python 复制代码
import sys

def solve():
    input = sys.stdin.readline
    
    n, q = map(int, input().split())
    s = input().strip()
    
    # 使用双哈希来减少冲突概率
    MOD1 = 10**9 + 7
    MOD2 = 10**9 + 9
    base = 131  # 选择一个质数作为基数
    
    # 计算前缀哈希值
    h1 = [0] * (n + 1)
    h2 = [0] * (n + 1)
    pow1 = [1] * (n + 1)
    pow2 = [1] * (n + 1)
    
    for i in range(1, n + 1):
        # 将字符映射为数字,从1开始
        val = ord(s[i-1]) - ord('a') + 1
        
        h1[i] = (h1[i-1] * base + val) % MOD1
        h2[i] = (h2[i-1] * base + val) % MOD2
        
        pow1[i] = (pow1[i-1] * base) % MOD1
        pow2[i] = (pow2[i-1] * base) % MOD2
    
    # 计算子串哈希值的函数
    def get_hash(l, r):
        # 子串 s[l:r] 的哈希值,这里使用闭区间 [l, r]
        hash1 = (h1[r] - h1[l-1] * pow1[r-l+1]) % MOD1
        hash2 = (h2[r] - h2[l-1] * pow2[r-l+1]) % MOD2
        
        # 确保结果为非负数
        if hash1 < 0:
            hash1 += MOD1
        if hash2 < 0:
            hash2 += MOD2
            
        return hash1, hash2
    
    # 处理查询
    results = []
    for _ in range(q):
        l1, r1, l2, r2 = map(int, input().split())
        
        # 获取两个子串的哈希值
        hash1_a, hash2_a = get_hash(l1, r1)
        hash1_b, hash2_b = get_hash(l2, r2)
        
        # 如果双哈希值都相等,则认为字符串相同
        if hash1_a == hash1_b and hash2_a == hash2_b:
            results.append("Yes")
        else:
            results.append("No")
    
    sys.stdout.write("\n".join(results))

if __name__ == "__main__":
    solve()

第二题参考答案(Python版)

python 复制代码
import sys

def main():
    input = sys.stdin.read
    data = input().split()
    
    n, q = int(data[0]), int(data[1])
    s = data[2]
    
    # 选择两个不同的基数和模数
    base1 = 131
    base2 = 137
    mod1 = 10**9 + 7
    mod2 = 10**9 + 9
    
    # 预处理幂值
    pow1 = [1] * (n + 1)
    pow2 = [1] * (n + 1)
    for i in range(1, n + 1):
        pow1[i] = (pow1[i-1] * base1) % mod1
        pow2[i] = (pow2[i-1] * base2) % mod2
    
    # 计算前缀哈希值
    hash1 = [0] * (n + 1)
    hash2 = [0] * (n + 1)
    
    for i in range(1, n + 1):
        c = ord(s[i-1]) - ord('a') + 1
        hash1[i] = (hash1[i-1] * base1 + c) % mod1
        hash2[i] = (hash2[i-1] * base2 + c) % mod2
    
    # 计算子串哈希值的函数
    def get_hash(l, r):
        # 计算第一个哈希值
        h1 = (hash1[r] - hash1[l-1] * pow1[r-l+1]) % mod1
        if h1 < 0:
            h1 += mod1
        
        # 计算第二个哈希值
        h2 = (hash2[r] - hash2[l-1] * pow2[r-l+1]) % mod2
        if h2 < 0:
            h2 += mod2
        
        return (h1, h2)
    
    results = []
    idx = 3
    for _ in range(q):
        l1, r1, l2, r2 = int(data[idx]), int(data[idx+1]), int(data[idx+2]), int(data[idx+3])
        idx += 4
        
        hash_l1_r1 = get_hash(l1, r1)
        hash_l2_r2 = get_hash(l2, r2)
        
        if hash_l1_r1 == hash_l2_r2:
            results.append("Yes")
        else:
            results.append("No")
    
    sys.stdout.write("\n".join(results))

if __name__ == "__main__":
    main()
相关推荐
知识分享小能手21 分钟前
统计学学习教程,从入门到精通,参数估计 — 知识点详解与公式推导(10)
学习·机器学习·概率论
有Li24 分钟前
EvoMDT:用于多癌种结构化临床决策的自进化多智能体系统文献速递/医学智能体前沿
人工智能·学习·分类·文献·医学生
殷忆枫1 小时前
AI笔记三十七:AI边缘端道桥安全监测系统:YOLOv8n推理与Web监控全解析
笔记·yolo
稚南城才子,乌衣巷风流1 小时前
ST 表(Sparse Table)算法详解:原理、实现与应用
算法
hold?fish:palm2 小时前
9 找到字符串中所有字母异位词
c++·算法·leetcode
逸模2 小时前
轻加盟模式,稳住品牌统一调性的思路
笔记·建模·公装·翻模·交底
Sw1zzle2 小时前
算法入门(六):贪心算法 - 基础入门(Leetcode 121/455/860/376/738)
算法·leetcode·贪心算法
青山木2 小时前
Hot 100 --- 岛屿数量
java·数据结构·算法·leetcode·深度优先·广度优先
不会就选b2 小时前
算法日常・每日刷题--<归并排序>1
数据结构·算法
whyTeaFo3 小时前
GAMES101: Lecture 10: Geometry 1 (Introduction) ppt笔记
笔记