题目地址:
https://www.acwing.com/problem/content/description/3726/
给你单词 S S S和 Q Q Q个询问。每次询问,你会得到正整数 A , B , C A,B,C A,B,C和 D D D。我们令单词 X X X由 S S S的第 A A A到 B B B个字母组成,单词 Y Y Y由 S S S的第 C C C到 D D D个字母组成。你需要回答,是否能够重新排列单词 Y Y Y中的字母,得到单词 X X X。
输入格式:
第一行一个单词
S
S
S,仅由小写字母组成。
第二行一个正整数
Q
Q
Q。
接下来
Q
Q
Q行,每行四个整数
A
,
B
,
C
,
D
A,B,C,D
A,B,C,D。
输出格式:
每次询问,如果能,输出DA
,否则输出NE
。
数据范围:
1
≤
∣
S
∣
≤
50000
1≤|S|≤50000
1≤∣S∣≤50000,
1
≤
Q
≤
50000
1≤Q≤50000
1≤Q≤50000,
1
≤
A
≤
B
≤
∣
S
∣
1≤A≤B≤|S|
1≤A≤B≤∣S∣,
1
≤
C
≤
D
≤
∣
S
∣
1≤C≤D≤|S|
1≤C≤D≤∣S∣,
B
−
A
=
D
−
C
B−A=D−C
B−A=D−C
可以用前缀和来处理区间里每个字母出现的次数,询问的时候比较每个字母出现次数是否相等即可。代码如下:
#include <cstring>
#include <iostream>
using namespace std;
const int N = 5e4 + 10;
char s[N];
int n, q;
int a, b, c, d;
int cnt[26][N];
int main() {
scanf("%s", s + 1);
n = strlen(s + 1);
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 26; j++) cnt[j][i] = cnt[j][i - 1];
cnt[s[i] - 'a'][i]++;
}
scanf("%d", &q);
while (q--) {
scanf("%d%d%d%d", &a, &b, &c, &d);
bool res = true;
for (int i = 0; i < 26; i++)
if (cnt[i][b] - cnt[i][a - 1] != cnt[i][d] - cnt[i][c - 1]) {
res = false;
break;
}
res ? puts("DA") : puts("NE");
}
}
预处理时间 O ( l S ) O(l_S) O(lS),空间 O ( l S ) O(l_S) O(lS),每组询问时间复杂度 O ( 1 ) O(1) O(1)。