zoukankan      html  css  js  c++  java
  • [CF985F] Isomorphic Strings

    题目描述

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

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

    1. f((s_{i}))=(t_{i})​ for any index i ,
    2. for any character there is exactly one character that f(x)=y ,
    3. for any character there is exactly one character that 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 mm queries characterized by three integers x,y,lenx,y,len ( 1<=x,y<=n-len+1 ). For each query check if two substrings s[x... x+len−1] and s[ y... y+len−1] are isomorphic.

    输入输出格式

    输入格式:

    The first line contains two space-separated integers n and m ( 1<=n<=2 * 10^5 , 1<=m<=2* 10^5 ) — the length of the string ss and the number of queries.

    The second line contains string ss consisting of nn lowercase English letters.

    The following mm lines contain a single query on each line: x_{i}xi​ , y_{i}yi​ and len_{i}leni​ ( 1<=xi​,yi​<=n , 1<=leni​<=n−max(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] and 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 ;
    2. substrings "ab" and "ca" are isomorphic: f ( a )=c , f ( b )=a ;
    3. substrings "bac" and "aba" are not isomorphic since f(b) and f ( c ) must be equal to a at same time;
    4. substrings "bac" and "cab" are isomorphic: f ( b )=c , f ( a )=a , f ( c )=b .

    题解

    题目大意:给你一个完整字符串,长度为n,接下来有m个询问,每个询问包括三个关键字x,y,len起点1,起点2和长度,我们需要判断以x为起点长度为len的字串和以y为起点的长度为len的子串的映射是否合法,若合法输出(YES),否则输出(NO)

    题意应该很清晰
    题目要求,若映射合法,要求映射唯一,即x子串中的字母对应的映射应该在y中可以找到,同时y子串中的字母也应该可以在x子串中找到对应的元素
    所以我们可以对原子串的每个字母分别hash.

    inline void Hash() {
     for(lol i=1;i<=n;i++) 
    	 for(lol j=1;j<=26;j++)
    	  hash[i][j]=(hash[i-1][j]*base%mod+(lol)(s[i]==('a'+j-1)))%mod; 
    }
    

    其中hash[i][j]数组代表原子串的第i位,字母是j的hash值
    然后hash的基本操作就是把字符串变成一个进制数,所以我们可以预处理一下这个进制数上第i位的权值

    inline void init() { 
    sum[0]=1;
     for(lol i=1;i<=n;i++) 
    	sum[i]=sum[i-1]*base%mod; 
    }
    

    那么,我们要怎么比较这两个子串是否相等呢,假设把k进制换成10进制
    原字符串对应的hash值为12345
    x=2,len=3;
    我们要求的是234的hash值=hash[1234]-hash[1](*)sum[3] (10进制下的sum[3]=1000,可以看成在1后面补了3个0)
    那么应该很好理解了,这个子串对应的hash值就是hash[x+len-1]-hash[x-1](*)sum[len]

    y子串和x一样,然后判断一下每个字符的hash值相不相等就好了

    Code

    #include<bits/stdc++.h>
    #define in(i) (i=read())
    using namespace std;
    typedef long long lol;
    const lol base=131,mod=1e9+7;
    lol read() {
        lol ans=0,f=1; char i=getchar();
        while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
        while(i>='0' && i<='9') {ans=(ans<<1)+(ans<<3)+i-'0'; i=getchar();}
        return ans*f;
    }
    lol l,r,len,n,m;
    char s[200010];
    lol sum[200010],hash[200010][30];
    inline void Hash() {
        for(lol i=1;i<=n;i++)
            for(lol j=1;j<=26;j++)
                hash[i][j]=(hash[i-1][j]*base%mod+(lol)(s[i]==('a'+j-1)))%mod;
    }
    inline void init() {
        sum[0]=1;
        for(lol i=1;i<=n;i++) sum[i]=sum[i-1]*base%mod;
    }
    bool check() {
        lol a[27],b[27];
        for(lol i=1;i<=26;i++) {
            a[i]=(hash[l+len-1][i]-sum[len]*hash[l-1][i]%mod+mod)%mod;
            b[i]=(hash[r+len-1][i]-sum[len]*hash[r-1][i]%mod+mod)%mod;
        }
        sort(a+1,a+27); sort(b+1,b+27);
        for(lol i=1;i<=26;i++) if(a[i]!=b[i]) return 0;
        return 1;
    }
    int main()
    {
        in(n); in(m); scanf("%s",s+1);
        Hash(); init();
        while(m--) {
            in(l); in(r); in(len);
            if(check()) puts("YES");
            else puts("NO");
        }
        return 0;
    }
    

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    研究生第二学期总结
    Android应用开发EditText文本内容变化监听方法
    Android 自定义动画 Loading
    UML建模之活动图介绍(Activity Diagram)
    UML学习(二)-----类图
    UML系列图--用例图
    Lesson9 some interesting things in C#
    Lesson10 Fianl and fellings
    Lesson 7: C#多线程
    浅谈android Socket 通信及自建ServerSocket服务端常见问题
  • 原文地址:https://www.cnblogs.com/real-l/p/9361301.html
Copyright © 2011-2022 走看看