题意:给你一个长度为n的字符串, m次询问, 每次输入一个s, t, l, 是的 [s,s+l-1] 与 [t,t+l-1] 里面的字符一一对应。并且只能一对一 不能一对多也不能多对一。
题解:Hash求解, 对于这段区间, 找到某个字符对应的字符, 将Hash值转变过去, 最后判断相不相等。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define pb push_back 5 const LL mod = (int)1e9+7; 6 const LL base = 131; 7 const int N = 2e5 + 100; 8 char str[N]; 9 int val[N][30]; 10 LL Hash[N]; 11 int n, m; 12 void init(){ 13 Hash[0] = 1; 14 for(int i = 1; i < N; i++) 15 Hash[i] = (Hash[i-1]*base)%mod; 16 } 17 void getHash(){ 18 for(int i = 1; i <= n; i++){ 19 for(int j = 0; j <= 26; j++) 20 val[i][j] = (val[i-1][j]*base) % mod; 21 int id = str[i] - 'a' + 1; 22 val[i][id] = (val[i][id]+1) % mod; 23 val[i][0] = (val[i][0] + str[i]-'a'+1)%mod; 24 } 25 } 26 LL Get(int id,int l, int r){ 27 return ((val[r][id] - val[l-1][id]*Hash[r-l+1]) % mod + mod) % mod; 28 } 29 int vis[27]; 30 vector<int> son[27]; 31 int main(){ 32 scanf("%d%d", &n, &m); 33 scanf("%s", str+1); 34 init(); 35 getHash(); 36 for(int i = 1; i <= n; i++) son[str[i]-'a'].pb(i); 37 for(int i = 0; i < 26; i++) son[i].pb(n+1); 38 int s, t, l; 39 LL t1, t2; 40 while(m--){ 41 memset(vis, 0, sizeof(vis)); 42 scanf("%d%d%d", &s, &t, &l); 43 t1 = Get(0,t,t+l-1); 44 t2 = 0; 45 int f = 1; 46 for(int i = 0; i < 26; i++){ 47 int pos = *lower_bound(son[i].begin(), son[i].end(), s); 48 if(pos > s+l-1) continue; 49 int tt = str[t+(pos-s)] - 'a'; 50 if(vis[tt]) {f = 0; break;} 51 else vis[tt] = 1; 52 t2 += Get(i+1,s,s+l-1) * (tt+1); 53 } 54 t2 %= mod; 55 if(f && t1 == t2) puts("YES"); 56 else puts("NO"); 57 } 58 return 0; 59 }