思路:
字符串hash
对于每一个字母单独hash
对于一段区间,求出每个字母的hash值,然后排序,如果能匹配上,就说明在这段区间存在字母间的一一映射
代码:
#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pii pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); //head const int N = 2e5 + 5; const int MOD = 1e9 + 7; const int base = 13; char s[N]; LL Hash[N][26], p[N], t[30], tt[30]; LL get_H(int l, int r, int i) { return ((Hash[r][i] - Hash[l-1][i]*p[r-l+1])%MOD + MOD)%MOD; } bool check(int x, int y, int len) { for (int i = 0; i < 26; i++) { t[i] = get_H(x, x+len-1, i); tt[i] = get_H(y, y+len-1, i); } sort(t, t+26); sort(tt, tt+26); for (int i = 0; i < 26; i++) if(t[i] != tt[i]) return false; return true; } int main() { int n, m, x, y, len; scanf("%d%d", &n, &m); scanf("%s", s+1); p[0] = 1; for (int i = 1; i <= n; i++) p[i] = (p[i-1] * base) % MOD; for (int i = 1; i <= n; i++) { for (int j = 0; j < 26; j++) { Hash[i][j] = (Hash[i-1][j] * base + (s[i] == 'a'+j))%MOD; } } while(m--) { scanf("%d%d%d", &x, &y, &len); if(check(x, y, len)) puts("YES"); else puts("NO"); } return 0; }