题意:
给 定 一 个 长 度 为 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。 给定一个长度为n的母串s,以及m个询问,每个询问包含两个起点x,y以及长度len。在s中,若分别从x和y起始的,长度为len的子串中的每一个字符能够一一对应,输出YES,否则输出NO。
样 例 : 输 入 : 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。 样例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。
数 据 范 围 : 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,n−max(x,y)+1]。
题解:
对 给 定 区 间 的 子 串 中 的 每 一 个 字 母 进 行 哈 希 。 对给定区间的子串中的每一个字母进行哈希。 对给定区间的子串中的每一个字母进行哈希。
首 先 , 分 别 计 算 两 个 子 串 的 哈 希 值 , 对 每 一 个 字 母 需 要 计 算 26 次 , 在 该 字 母 对 应 的 位 置 标 记 , 因 为 本 题 中 , 我 们 关 心 的 是 字 母 之 间 一 一 对 应 的 关 系 , 与 字 母 本 身 没 有 关 系 。 就 是 将 每 一 个 字 母 对 应 成 一 个 26 位 的 二 进 制 数 , 字 母 所 对 应 的 序 号 位 上 为 1 , 其 他 位 为 0 , 如 a : 100...00 。 首先,分别计算两个子串的哈希值,对每一个字母需要计算26次,在该字母对应的位置标记,\\因为本题中,我们关心的是字母之间一一对应的关系,与字母本身没有关系。\\就是将每一个字母对应成一个26位的二进制数,字母所对应的序号位上为1,其他位为0,如a:100...00。 首先,分别计算两个子串的哈希值,对每一个字母需要计算26次,在该字母对应的位置标记,因为本题中,我们关心的是字母之间一一对应的关系,与字母本身没有关系。就是将每一个字母对应成一个26位的二进制数,字母所对应的序号位上为1,其他位为0,如a:100...00。
然 后 用 数 组 a 和 b 来 存 储 两 个 子 串 所 在 区 间 对 应 的 哈 希 值 , 将 结 果 排 序 后 , 看 每 个 字 母 的 哈 希 值 能 否 一 一 对 应 即 可 。 然后用数组a和b来存储两个子串所在区间对应的哈希值,将结果排序后,看每个字母的哈希值能否一一对应即可。 然后用数组a和b来存储两个子串所在区间对应的哈希值,将结果排序后,看每个字母的哈希值能否一一对应即可。
举 个 栗 子 : 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个哈希值,按顺序得到如下结果,注意要排序后再看能否一一对应。 举个栗子:bac与aba对bac:每个字母对应哈希为0100...00、1000...00、0010..00对aba:每个字母对应哈希为1000...00、0100...00、1000..00最后分别对bac和aba计算数组a和b的26个哈希值,按顺序得到如下结果,注意要排序后再看能否一一对应。
注意:
① 、 u l l 自 然 溢 出 在 本 题 被 卡 , 可 以 选 择 一 些 质 数 取 模 来 减 少 冲 突 概 率 。 ② 、 在 计 算 哈 希 值 时 , 乘 积 可 能 发 生 i n t 溢 出 , 因 此 所 有 数 据 用 l l 来 存 比 较 好 。 ①、ull自然溢出在本题被卡,可以选择一些质数取模来减少冲突概率。\\②、在计算哈希值时,乘积可能发生int溢出,因此所有数据用ll来存比较好。 ①、ull自然溢出在本题被卡,可以选择一些质数取模来减少冲突概率。②、在计算哈希值时,乘积可能发生int溢出,因此所有数据用ll来存比较好。
代码:
#include
#include
#include
#include
#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;
}