题解:AcWing 841 字符串哈希

【题目来源】

AcWing:841. 字符串哈希 - AcWing题库

【题目描述】

给定一个长度为n的字符串,再给定m个询问,每个询问包含四个整数 11,r1,12,r2,请你判断[11,r1]和[12,r2]这两个区间所包含的字符串子串是否完全相同。

字符串中只包含大小写英文字母和数字。+

【输入】

第一行包含整数n和m,表示字符串长度和询问次数。

第二行包含一个长度为n的字符串,字符串中只包含大小写英文字母和数字。

接下来m行,每行包含四个整数11,r1,12,r2,表示一次询问所涉及的两个区间。

注意,字符串的位置从1开始编号。

【输出】

对于每个询问输出一个结果,如果两个字符串子串完全相同则输出 Yes,否则输出No。每个结果占一行。

【输入样例】

8 3
aabbaabb
1 3 5 7
1 3 6 8
1 2 1 2

【输出样例】

Yes
No
Yes

【解题思路】

image

【算法标签】

《AcWing 841 字符串哈希》 #字符串哈希# #哈希#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ULL;  // 使用无符号长整型,自然溢出相当于取模2^64
const int N = 100010;            // 字符串最大长度
const int P = 131;               // 进制基数,经验值,131或13331

int n, m;        // n: 字符串长度, m: 查询次数
char str[N];     // 存储字符串,下标从1开始
ULL h[N];        // 前缀哈希数组,h[i]表示前i个字符的哈希值
ULL p[N];        // 幂数组,p[i] = P^i

// 获取子串str[l..r]的哈希值
ULL get(int l, int r)
{
    // 计算哈希值公式:h[l..r] = h[r] - h[l-1] * p[r-l+1]
    return h[r] - h[l - 1] * p[r - l + 1];
}

int main()
{
    // 输入字符串长度、查询次数和字符串
    // str+1表示从str[1]开始存储,使下标从1开始
    scanf("%d%d%s", &n, &m, str + 1);
  
    // 初始化幂数组
    p[0] = 1;  // P^0 = 1
    for (int i = 1; i <= n; i++)
    {
        // 计算P的i次幂
        p[i] = p[i - 1] * P;
      
        // 计算前i个字符的哈希值
        // 递推公式:h[i] = h[i-1] * P + str[i]
        h[i] = h[i - 1] * P + str[i];
    }
  
    // 处理每次查询
    while (m--)
    {
        int l1, r1, l2, r2;  // 两个子串的起始和结束位置
        scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
      
        // 比较两个子串的哈希值
        if (get(l1, r1) == get(l2, r2))
        {
            puts("Yes");  // 哈希值相同,子串相同
        }
        else
        {
            puts("No");   // 哈希值不同,子串不同
        }
    }
  
    return 0;
}

【运行结果】

8 3
aabbaabb
1 3 5 7 
Yes
1 3 6 8
No
1 2 1 2
Yes
posted @ 2026-02-21 20:01  团爸讲算法  阅读(0)  评论(0)    收藏  举报