CF985F Isomorphic Strings

Posted five20

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF985F Isomorphic Strings相关的知识,希望对你有一定的参考价值。

题目描述

You are given a string s s s of length n n n consisting of lowercase English letters.

For two given strings s s s and t t t , say S S S is the set of distinct characters of s s s and T T T is the set of distinct characters of t t t . The strings s s s and t t t are isomorphic if their lengths are equal and there is a one-to-one mapping (bijection) f f f between S S S and T T T for which f(si)=ti f(s_{i})=t_{i} f(si?)=ti? . Formally:

  1. f(si)=ti f(s_{i})=t_{i} f(si?)=ti? for any index i i i ,
  2. for any character 技术分享图片 there is exactly one character 技术分享图片 that f(x)=y f(x)=y f(x)=y ,
  3. for any character 技术分享图片 there is exactly one character 技术分享图片 that f(x)=y f(x)=y f(x)=y .

For example, the strings "aababc" and "bbcbcz" are isomorphic. Also the strings "aaaww" and "wwwaa" are isomorphic. The following pairs of strings are not isomorphic: "aab" and "bbb", "test" and "best".

You have to handle m m m queries characterized by three integers x,y,len x,y,len x,y,len ( 1<=x,y<=n−len+1 1<=x,y<=n-len+1 1<=x,y<=nlen+1 ). For each query check if two substrings s[x... x+len−1] s[x... x+len-1] s[x... x+len1] and s[y... y+len−1] s[y... y+len-1] s[y... y+len1] are isomorphic.

输入输出格式

输入格式:

The first line contains two space-separated integers n n n and m m m ( 1<=n<=2⋅105 1<=n<=2·10^{5} 1<=n<=2105 , 1<=m<=2⋅105 1<=m<=2·10^{5} 1<=m<=2105 ) — the length of the string s s s and the number of queries.

The second line contains string s s s consisting of n n n lowercase English letters.

The following m m m lines contain a single query on each line: xi x_{i} xi? , yi y_{i} yi? and leni len_{i} leni? ( 1<=xi,yi<=n 1<=x_{i},y_{i}<=n 1<=xi?,yi?<=n , 1<=leni<=n−max(xi,yi)+1 1<=len_{i}<=n-max(x_{i},y_{i})+1 1<=leni?<=nmax(xi?,yi?)+1 ) — the description of the pair of the substrings to check.

输出格式:

For each query in a separate line print "YES" if substrings s[xi... xi+leni−1] s[x_{i}... x_{i}+len_{i}-1] s[xi?... xi?+leni?1] and s[yi... yi+leni−1] s[y_{i}... y_{i}+len_{i}-1] s[yi?... yi?+leni?1] are isomorphic and "NO" otherwise.

输入输出样例

输入样例#1: 
7 4
abacaba
1 1 1
1 4 2
2 1 3
2 4 3
输出样例#1: 
YES
YES
NO
YES

说明

The queries in the example are following:

  1. substrings "a" and "a" are isomorphic: f(a)=a f(a)=a f(a)=a ;
  2. substrings "ab" and "ca" are isomorphic: f(a)=c f(a)=c f(a)=c , f(b)=a f(b)=a f(b)=a ;
  3. substrings "bac" and "aba" are not isomorphic since f(b) f(b) f(b) and f(c) f(c) f(c) must be equal to a a a at same time;
  4. substrings "bac" and "cab" are isomorphic: f(b)=c f(b)=c f(b)=c , f(a)=a f(a)=a f(a)=a , f(c)=b f(c)=b f(c)=b .
 
Solution:
  本题还是HRZ学长讲的算法,也是贼有意思。
  题意中的相似就并不在意字符具体是什么,而在于字符的排列情况是否能一致,而若我们用$26$个字母分别为关键字弄出$26$个$0,1$串,那么一个字符串的相对位置关系是可以用这$26$个$0,1$排列来唯一确定。
  于是,我们对整个字符串分别以$26$个字母为关键字进行hash,解释一下关键字意思是比如$a$字符为关键字,那么所有非$a$的字符所对应的$K$进制位为$0$,只有为该关键字的位为$1$,这样就能保证相似的排列对应的hash值一致,而整个hash过程也就$O(n)$递推一遍就好了。
  然后对于每次询问,我们就将两段字符串的$26$个hash值取出来,分别用$a,b$数组存下来,从小到大排序,然后比较是否相等即可。
  注意本题hack模数$998244353$,所以我改用了$19260817$做单模数,当然更建议用多模数减少错误率。
代码:
 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define ll long long
 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
 6 using namespace std;
 7 const int N=200005,M=131,mod2=998244353,mod1=19260817;
 8 int n,m,x,y,len;
 9 ll f[N][27],sum[N],a[27],b[27];
10 char s[N];
11 
12 il int gi(){
13     int a=0;char x=getchar();bool f=0;
14     while((x<0||x>9)&&x!=-)x=getchar();
15     if(x==-)x=getchar(),f=1;
16     while(x>=0&&x<=9)a=(a<<3)+(a<<1)+x-48,x=getchar();
17     return f?-a:a;
18 }
19 
20 il bool check(){
21     For(i,1,26) 
22         a[i]=(f[x+len-1][i]-f[x-1][i]*sum[len]%mod1+mod1)%mod1,
23         b[i]=(f[y+len-1][i]-f[y-1][i]*sum[len]%mod1+mod1)%mod1;
24     sort(a+1,a+27),sort(b+1,b+27);
25     For(i,1,26) if(a[i]!=b[i])return 0;
26     return 1;
27 }
28 
29 int main(){
30     n=gi(),m=gi();
31     scanf("%s",s+1);
32     sum[0]=1;
33     For(i,1,n) {
34         sum[i]=(sum[i-1]*M)%mod1;
35         For(j,1,26) f[i][j]=(f[i-1][j]*M%mod1+(s[i]==a+j-1?1:0))%mod1;    
36     }
37     while(m--){
38         x=gi(),y=gi(),len=gi();
39         (check())?puts("YES"):puts("NO");
40     }
41     return 0;
42 }

 

以上是关于CF985F Isomorphic Strings的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces985F:Isomorphic Strings (字符串&hash)

205. Isomorphic Strings

LeetCode Isomorphic Strings

LeetCode-Isomorphic Strings

205. Isomorphic Strings [easy] (Python)

[LeetCode] 205 Isomorphic Strings