codeforces 985F(hash)

  • Post author:
  • Post category:其他


首先本题目的意思是给定一个母串,然后每次查询两个长度相等的子串是否同构,同构的定义如下:

For two given strings


s


and


t


, say


S


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)


f


between


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

“.

要求对S中某一特定字母,总能找到在T中的某一字母与其字母出现个数相同,且每个出现字母对应的位置相同,

解法:

对26个字母建立26个boolean数组,例如 b[0][1]代表字母a是否在1位置出现,若出现则记为1,没有出现记为0.

这样若两个等长子串同构,则必然对其所在子串的对应到建立的26个数组子串哈希值排序之后对应相等。

(不太会说,觉得难以理解可以留言)

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn  = 2e5 + 100;
const int MOD = 1e9+7;
const int N =  27;
int b[N][maxn];
int p[maxn];
int n,m;
char s[maxn];
int get(int id ,int l ,int r){
    return (b[id][r] - (l == 0 ? 0 : b[id][l-1]) + MOD) % MOD;
}
int main()
{
    cin>>n>>m;
    gets(s); gets(s);
    p[0] = 1; for(int i=1;i<=n;i++) p[i] = p[i - 1] * 2 %MOD;
    for(int i=0;i<26;i++)
     for(int j=0;j<n;j++){
          b[i][j] = (b[i][j-1] + 1ll* p[j] *(s[j]=='a'+i)%MOD) %MOD;
     }
    int xx[N],yy[N];
    while(m--){
         int x , y , len ;
         scanf("%d %d %d",&x,&y,&len); --x,--y;
         if(x > y) swap(x , y);
         for(int i=0;i<26;i++) xx[i]=1ll * p[y - x] * get(i,x , x + len -1) % MOD,yy[i]=get(i , y, y + len - 1);
         sort(yy , yy + 26) ;
         sort(xx , xx + 26);
         int ok  =1 ;
         for(int i = 0 ;i<26;i++)
         if(xx[i] != yy[i]) {
              ok = 0;
              break;
         }
         printf("%s\n",ok ? "YES":"NO");
    }
    return 0;
}



版权声明:本文为playwfun原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。