zoukankan      html  css  js  c++  java
  • ACwing 841

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

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

    输入格式

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

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

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

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

    输出格式

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

    每个结果占一行。

    数据范围

    1 ≤ n, m ≤ 105
    输入样例:
    8 3
    aabbaabb
    1 3 5 7
    1 3 6 8
    1 2 1 2

    输出样例:

    Yes
    No
    Yes

    题目大意:

    输入n和m,表示有一个长度为 n 的字符串和 m 个询问,再输入长度为 n 的字符串,接下来是m个询问,每次询问给出两个区间[l1, r1], [l2, r2] ,询问这个串中这两个区间是否完全相等,并输出yes or no。

    解题思路:

    字符串hash模板题,判断串中两个子串是否相等时,可以用字符串hash去解决,接下来介绍字符串hash的具体思路:

    字符串hash:

    开两个数组h[] 和p[] , h i 表示前 i 个字符的哈希值,p i 表示 P 的 i 次方,对于前 n 个字符的哈希值是这样求的,将其看作 n 位的 p 进制数模除一个数,假设ABCD 则 h[4] 的哈希值就是 A * p3 + B * p2 + C * p1 + D * p0, 关于取模,这里一般选择264,然后数组开unsigned long long , 这样不用刻意取模,因为64位无符号 int 的溢出机制就是对 264 取模。先预处理p[n] 和 h[n],p进制数,前面为高位,则递推公式为p[i] = p[i - 1] * P,注意p[0]应为1,然后h[i] = h[i - 1] * p + str[i](默认将其映射为ASCII码,一定注意不能映射成0,因为这样A,AAAAAA,AAAAAA的哈希值都一样了),这里的p进制,p为131或13331, 能最大化减少冲突(因为哈希表是有可能出现冲突的),之后对于两个区间的判断,实质上就是判断两个区间的哈希值是否相等,对于区间[l, r] , 我们知道h[r] 和 h[l - 1] 的哈希值,但是高位对应的不一样,所以要将h[r - 1] * pr-(l-1) = h[r - 1] * pr-l+1, 之后比较两个区间的哈希值即可。

    Code:

    #include <iostream>
    
    using namespace std;
    
    typedef unsigned long long ull;
    
    const int N = 1e5 + 50;
    
    ull h[N], p[N];
    char str[N];
    
    ull geth(int l, int r)//求区间哈希值
    {
        return h[r] - h[l - 1] * p[r - l + 1];
    }
    
    int main()
    {
        int n, m;
        scanf("%d%d%s", &n, &m, str + 1);
        p[0] = 1;
        
        for (int i = 1; i <= n; i ++)//递推一下h 和 p P取131 || 13331
        {
            p[i] = p[i - 1] * 131;
            h[i] = h[i - 1] * 131 + str[i];
        }
        
        while (m--)
        {
            int l1, r1, l2, r2;
            scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
            
            puts(geth(l1, r1) == geth(l2, r2) ? "Yes" : "No");//判断两个区间的哈希值是否相同
        }
        
        return 0;
    }
    
  • 相关阅读:
    $router和$route的区别
    提莫攻击
    paste命令
    数组中的第K个最大元素
    od命令
    被围绕的区域
    不用虚机不用Docker使用Azure应用服务部署ASP.NET Core程序
    面试官:对象可能会迟到,但它永远不会缺席
    Kubernetes 的层级命名空间介绍
    每日一道 LeetCode (21):对称二叉树
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294144.html
Copyright © 2011-2022 走看看