从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()
相关推荐
日更嵌入式的打工仔7 分钟前
RS-485通讯协议
笔记·嵌入式硬件
龙山云仓8 分钟前
No131:AI中国故事-对话荀子——性恶论与AI约束:礼法并用、化性起伪与算法治理
大数据·人工智能·深度学习·算法·机器学习
嗯嗯=12 分钟前
STM32单片机学习篇5
stm32·单片机·学习
夏鹏今天学习了吗16 分钟前
【LeetCode热题100(90/100)】编辑距离
算法·leetcode·职场和发展
数据轨迹00118 分钟前
ICCV MK-UNet:多核深度可分离卷积医学分割
经验分享·笔记·facebook·oneapi·twitter
芒克芒克43 分钟前
数组去重进阶:一次遍历实现最多保留指定个数重复元素(O(n)时间+O(1)空间)
数据结构·算法
星火开发设计1 小时前
二维数组:矩阵存储与多维数组的内存布局
开发语言·c++·人工智能·算法·矩阵·函数·知识
头疼的程序员1 小时前
计算机网络:自顶向下方法(第七版)第二章 学习分享(二)
学习·计算机网络
丨康有为丨1 小时前
算法时间复杂度和空间复杂度
算法
HarmonLTS2 小时前
Python人工智能深度开发:技术体系、核心实践与工程化落地
开发语言·人工智能·python·算法