zoukankan      html  css  js  c++  java
  • 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+leni1] and s[yi... yi+leni−1] s[y_{i}... y_{i}+len_{i}-1] s[yi... yi+leni1] 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$做单模数,当然更建议用多模数减少错误率。
    代码:
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    const int N=200005,M=131,mod2=998244353,mod1=19260817;
    int n,m,x,y,len;
    ll f[N][27],sum[N],a[27],b[27];
    char s[N];
    
    il int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar();
        return f?-a:a;
    }
    
    il bool check(){
        For(i,1,26) 
            a[i]=(f[x+len-1][i]-f[x-1][i]*sum[len]%mod1+mod1)%mod1,
            b[i]=(f[y+len-1][i]-f[y-1][i]*sum[len]%mod1+mod1)%mod1;
        sort(a+1,a+27),sort(b+1,b+27);
        For(i,1,26) if(a[i]!=b[i])return 0;
        return 1;
    }
    
    int main(){
        n=gi(),m=gi();
        scanf("%s",s+1);
        sum[0]=1;
        For(i,1,n) {
            sum[i]=(sum[i-1]*M)%mod1;
            For(j,1,26) f[i][j]=(f[i-1][j]*M%mod1+(s[i]=='a'+j-1?1:0))%mod1;    
        }
        while(m--){
            x=gi(),y=gi(),len=gi();
            (check())?puts("YES"):puts("NO");
        }
        return 0;
    }
  • 相关阅读:
    剑指 Offer 41. 数据流中的中位数
    剑指 Offer 19. 正则表达式匹配
    leetcode 75 颜色分类
    Deepin 添加 open as root
    window 下 无损进行其他文件系统(ext4) 到 ntfs 文件系统的转化
    Windows Teminal Preview Settings
    CentOS 7 容器内替换 apt-get 源为阿里源
    Ubuntu 20.04 安装 Consul
    elementary os 15 添加Open folder as root
    elementary os 15 gitbook install
  • 原文地址:https://www.cnblogs.com/five20/p/9353800.html
Copyright © 2011-2022 走看看