字符串哈希-Isomorphic Strings-CF985F

字符串哈希-Isomorphic Strings-CF985F

题意:

给 定 一 个 长 度 为 n 的 母 串 s , 以 及 m 个 询 问 , 每 个 询 问 包 含 两 个 起 点 x , y 以 及 长 度 l e n 。 在 s 中 , 若 分 别 从 x 和 y 起 始 的 , 长 度 为 l e n 的 子 串 中 的 每 一 个 字 符 能 够 一 一 对 应 , 输 出 Y E S , 否 则 输 出 N O 。 给定一个长度为n的母串s,以及m个询问,每个询问包含两个起点x,y以及长度len。\\在s中,若分别从x和y起始的,长度为len的子串中的每一个字符能够一一对应,输出YES,否则输出NO。 nsmx,ylensxylenYESNO

样 例 : 输 入 : 74 a b a c a b a 1   1   1 1   4   2 2   1   3 2   4   3 输 出 : Y E S Y E S N O Y E S 样例:\\输入:\\7 4 \\abacaba \\1 \ 1 \ 1 \\1 \ 4 \ 2 \\2 \ 1\ 3 \\2 \ 4 \ 3\\输出:\\YES\\YES\\NO\\YES 74abacaba1 1 11 4 22 1 32 4 3:YESYESNOYES

样 例 1 : 从 1 开 始 的 两 个 长 度 为 1 的 子 串 , a 与 a 形 成 映 射 即 f ( a ) = a 。 样 例 2 : 从 1 开 始 和 从 4 开 始 的 两 个 长 度 为 2 的 子 串 , a b 与 c a 形 成 映 射 即 f ( a ) = c , f ( b ) = a 。 样 例 3 : 从 2 开 始 和 从 1 开 始 的 两 个 长 度 为 3 的 子 串 , b a c 与 a b a 未 能 构 成 一 一 映 射 , f ( b ) = a 与 f ( c ) = a 冲 突 。 样 例 4 : 从 2 开 始 和 从 4 开 始 的 两 个 长 度 为 3 的 子 串 , b a c 与 c a b 形 成 映 射 即 f ( b ) = c , f ( a ) = a , f ( c ) = b 。 样例1:从1开始的两个长度为1的子串,a与a形成映射即f(a)=a。\\样例2:从1开始和从4开始的两个长度为2的子串,ab与ca形成映射即f(a)=c,f(b)=a。\\样例3:从2开始和从1开始的两个长度为3的子串,bac与aba未能构成一一映射,f(b)=a与f(c)=a冲突。\\样例4:从2开始和从4开始的两个长度为3的子串,bac与cab形成映射即f(b)=c,f(a)=a,f(c)=b。 111,aaf(a)=a2142,abcaf(a)=c,f(b)=a3213,bacabaf(b)=af(c)=a4243,baccabf(b)=c,f(a)=a,f(c)=b

数 据 范 围 : n , m ∈ [ 1 , 200000 ] , x , y ∈ [ 1 , n ] , l e n ∈ [ 1 , n − m a x ( x , y ) + 1 ] 。 数据范围:n,m∈[1,200000],x,y∈[1,n],len∈[1,n-max(x,y)+1]。 n,m[1,200000],x,y[1,n],len[1,nmax(x,y)+1]

题解:

对 给 定 区 间 的 子 串 中 的 每 一 个 字 母 进 行 哈 希 。 对给定区间的子串中的每一个字母进行哈希。

首 先 , 分 别 计 算 两 个 子 串 的 哈 希 值 , 对 每 一 个 字 母 需 要 计 算 26 次 , 在 该 字 母 对 应 的 位 置 标 记 , 因 为 本 题 中 , 我 们 关 心 的 是 字 母 之 间 一 一 对 应 的 关 系 , 与 字 母 本 身 没 有 关 系 。 就 是 将 每 一 个 字 母 对 应 成 一 个 26 位 的 二 进 制 数 , 字 母 所 对 应 的 序 号 位 上 为 1 , 其 他 位 为 0 , 如 a : 100...00 。 首先,分别计算两个子串的哈希值,对每一个字母需要计算26次,在该字母对应的位置标记,\\因为本题中,我们关心的是字母之间一一对应的关系,与字母本身没有关系。\\就是将每一个字母对应成一个26位的二进制数,字母所对应的序号位上为1,其他位为0,如a:100...00。 262610a:100...00

然 后 用 数 组 a 和 b 来 存 储 两 个 子 串 所 在 区 间 对 应 的 哈 希 值 , 将 结 果 排 序 后 , 看 每 个 字 母 的 哈 希 值 能 否 一 一 对 应 即 可 。 然后用数组a和b来存储两个子串所在区间对应的哈希值,将结果排序后,看每个字母的哈希值能否一一对应即可。 ab

举 个 栗 子 : b a c 与 a b a 对 b a c : 每 个 字 母 对 应 哈 希 为 0100...00 、 1000...00 、 0010..00 对 a b a : 每 个 字 母 对 应 哈 希 为 1000...00 、 0100...00 、 1000..00 最 后 分 别 对 b a c 和 a b a 计 算 数 组 a 和 b 的 26 个 哈 希 值 , 按 顺 序 得 到 如 下 结 果 , 注 意 要 排 序 后 再 看 能 否 一 一 对 应 。 举个栗子:bac与aba\\对bac:每个字母对应哈希为0100...00、1000...00、0010..00\\对aba:每个字母对应哈希为1000...00、0100...00、1000..00\\最后分别对bac和aba计算数组a和b的26个哈希值,按顺序得到如下结果,注意要排序后再看能否一一对应。 bacababac:0100...001000...000010..00aba:1000...000100...001000..00bacabaab26
在这里插入图片描述

注意:

① 、 u l l 自 然 溢 出 在 本 题 被 卡 , 可 以 选 择 一 些 质 数 取 模 来 减 少 冲 突 概 率 。 ② 、 在 计 算 哈 希 值 时 , 乘 积 可 能 发 生 i n t 溢 出 , 因 此 所 有 数 据 用 l l 来 存 比 较 好 。 ①、ull自然溢出在本题被卡,可以选择一些质数取模来减少冲突概率。\\②、在计算哈希值时,乘积可能发生int溢出,因此所有数据用ll来存比较好。 ullintll


代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int N=2e5+10;
const int base=131;
const int mod=19260817;
int n,m;
ll p[N],h[N][27];
char s[N];

ll get(int l,int r,int i)
{
    return (h[r][i]-(h[l-1][i]*p[r-l+1])%mod+mod)%mod;
}

bool check(int x,int y,int len)
{
    ll a[27],b[27];
    for(int i=1;i<=26;i++)
    {
        a[i]=get(x,x+len-1,i);
        b[i]=get(y,y+len-1,i);
    }

    sort(a+1,a+27);sort(b+1,b+27);

    for(int i=1;i<=26;i++) if(a[i]!=b[i]) return false;
    return true;
}

int main()
{
    scanf("%d%d",&n,&m);
    scanf("%s",s+1);

    p[0]=1;
    for(int i=1;i<=n;i++) p[i]=(p[i-1]*base)%mod;

    for(int i=1;i<=n;i++)
        for(int j=1;j<=26;j++)
            h[i][j]=((h[i-1][j]*base)%mod+(s[i]==('a'+j-1)))%mod;

    int x,y,len;
    while(m--)
    {
        scanf("%d%d%d",&x,&y,&len);
        if(check(x,y,len)) puts("YES");
        else puts("NO");
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值