首先本题目的意思是给定一个母串,然后每次查询两个长度相等的子串是否同构,同构的定义如下:
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(si) = ti. Formally:
- f(si) = ti for any index i,
- for any character there is exactly one character that f(x) = y,
- 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;
}