题目大意:给你一个长度为n 由小写字母组成的字符串,有m个询问, 每个询问给你两个区间, 问你xi,yi能不能形成映射关系。
思路:这个题意好难懂啊。。。 字符串哈希, 将26个字符分开来hash, 那么check就变成啦, 区间内对应的26个字符的hash值是否一致。
即如果 a -> b 那么区间1内a的hash值等于区间2内b的hash值。
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define fi first 4 #define se second 5 #define mk make_pair 6 #define pii pair<int,int> 7 #define piii pair<int, pair<int,int>> 8 9 using namespace std; 10 11 const int N = 2e5 + 7; 12 const int M = 1e4 + 7; 13 const int inf = 0x3f3f3f3f; 14 const LL INF = 0x3f3f3f3f3f3f3f3f; 15 const int mod = 1e9 + 7; 16 17 int n, m; 18 LL hs[26][N], f[N], base = 17, seed = 11; 19 char s[N]; 20 21 vector<int> vec[26]; 22 LL getHash(int x, int l, int r) { 23 LL ans = hs[x][l]; 24 if(r < n - 1) ans -= hs[x][r + 1] * f[r - l + 1]; 25 ans = (ans % mod + mod) % mod; 26 return ans; 27 } 28 29 bool check(int l1, int r1, int l2, int r2) { 30 for(int j = 0; j < 26; j++) { 31 int p = lower_bound(vec[j].begin(), vec[j].end(), l1) - vec[j].begin(); 32 if(p >= vec[j].size() || vec[j][p] > r1) continue; 33 if(getHash(j, l1, r1) != getHash(s[l2 + (vec[j][p] - l1)] - 'a', l2, r2)) 34 return false; 35 } 36 return true; 37 } 38 int main() { 39 40 f[0] = 1; for(int i = 1; i < N; i++) f[i] = f[i - 1] * base % mod; 41 scanf("%d%d", &n, &m); 42 scanf("%s", s); 43 n = strlen(s); 44 45 46 for(int i = n - 1; i >= 0; i--) { 47 for(int j = 0; j < 26; j++) { 48 hs[j][i] = hs[j][i + 1] * base % mod; 49 if(j == s[i] - 'a') { 50 hs[j][i] = (hs[j][i] + seed) % mod; 51 } 52 } 53 } 54 55 for(int i = 0; i < n; i++) 56 vec[s[i] - 'a'].push_back(i); 57 58 while(m--) { 59 int x, y, len; 60 scanf("%d%d%d", &x, &y, &len); 61 int l1 = x - 1, l2 = y - 1, r1 = l1 + len - 1, r2 = l2 + len - 1; 62 63 if(check(l1, r1, l2, r2)) puts("YES"); 64 else puts("NO"); 65 } 66 return 0; 67 } 68 69 /* 70 */