从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()
相关推荐
生成论实验室12 分钟前
《事件关系阴阳博弈动力学:识势应势之道》第二篇:阴阳博弈——认知的动力学基础
数据结构·人工智能·科技·神经网络·算法
久菜盒子工作室28 分钟前
时寒冰:第五次产业大转移与未来30年国运:在“双向挤压”中实现惊险一跃
人工智能·学习
风筝在晴天搁浅41 分钟前
字节高频题 小于n的最大数
算法
LabVIEW开发43 分钟前
LabVIEW水力机组空蚀在线监测
算法·labview·labview知识·labview功能·labview程序
AI科技星1 小时前
科幻艺术书本封面:《全域数学》第一部·数术本源 第三卷 代数原本(P95-141)完整五级目录【乖乖数学】
算法·机器学习·数学建模·数据挖掘·量子计算
风筝在晴天搁浅1 小时前
LeetCode 92.反转链表Ⅱ
算法·leetcode·链表
王老师青少年编程1 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【贪心与二分判定】:数列分段 Section II
c++·算法·贪心·csp·信奥赛·二分判定·数列分段 section ii
V搜xhliang02461 小时前
OpenClaw科研全场景用法:从文献到实验室的完整自动化方案
运维·开发语言·人工智能·python·算法·microsoft·自动化
05候补工程师1 小时前
【ROS 2 具身智能】Gazebo 仿真避坑指南:从“幽灵机器人”到传感器数据流打通
人工智能·经验分享·笔记·ubuntu·机器人
chushiyunen2 小时前
pandas使用笔记、数据清洗、json_normalize
笔记·pandas