给定一个长度为 nn 的字符串,再给定 mm 个询问,每个询问包含四个整数 l1,r1,l2,r2l1,r1,l2,r2,请你判断 [l1,r1][l1,r1] 和 [l2,r2][l2,r2] 这两个区间所包含的字符串子串是否完全相同。
字符串中只包含大小写英文字母和数字。

输入格式

第一行包含整数 nn 和 mm,表示字符串长度和询问次数。
第二行包含一个长度为 nn 的字符串,字符串中只包含大小写英文字母和数字。
接下来 mm 行,每行包含四个整数 l1,r1,l2,r2l1,r1,l2,r2,表示一次询问所涉及的两个区间。
注意,字符串的位置从 11 开始编号。

输出格式

对于每个询问输出一个结果,如果两个字符串子串完全相同则输出 Yes,否则输出 No。
每个结果占一行。

数据范围

1≤n,m≤1051≤n,m≤105

输入样例:

8 3 aabbaabb 1 3 5 7 1 3 6 8 1 2 1 2

输出样例:

Yes No Yes


image.png

  1. #include <iostream>
  2. using namespace std;
  3. typedef unsigned long long ULL;
  4. const int N = 100010, P = 131; //经验值,131 或者13331
  5. int n,m;
  6. char str[N];
  7. ULL h[N],p[N];
  8. ULL get(int l, int r) {
  9. return h[r] - h[l-1] * p[r-l+1];
  10. }
  11. int main() {
  12. scanf("%d%d%s",&n,&m,str+1);
  13. p[0] = 1;
  14. for (int i = 1; i <= n; ++i) {
  15. p[i] = p[i-1] * P;
  16. h[i] = h[i-1] * P + str[i];
  17. }
  18. while (m--) {
  19. int l1,r1,l2,r2;
  20. scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
  21. if (get(l1,r1) == get(l2,r2)) puts("Yes");
  22. else puts("No");
  23. }
  24. return 0;
  25. }