题目描述
给定一个长度为 n 的字符串,再给定 m 个询问,每个询问包含四个整数 l1,r1,l2,r2,请你判断 [l1,r1] 和 [l2,r2] 这两个区间所包含的字符串子串是否完全相同。
字符串中只包含大小写英文字母和数字。
输入格式
第一行包含整数 n 和 m,表示字符串长度和询问次数。
第二行包含一个长度为 n 的字符串,字符串中只包含大小写英文字母和数字。
接下来 m 行,每行包含四个整数 l1,r1,l2,r2,表示一次询问所涉及的两个区间。
注意,字符串的位置从 1 开始编号。
输出格式
对于每个询问输出一个结果,如果两个字符串子串完全相同则输出 Yes,否则输出 No。
每个结果占一行。
数据范围
1≤n,m≤105
样例
输入样例:
8 3
aabbaabb
1 3 5 7
1 3 6 8
1 2 1 2
输出样例:
Yes
No
Yes
算法1
(暴力枚举)
时间复杂度:每一个询问的时间复杂度为O(n)
C++ 代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
string s;
cin>>s;
while(m--){
int a1,b1,a2,b2;
cin>>a1>>b1>>a2>>b2;
int t=a2-a1;
int i;
for(i=a1-1;i<=b1-1;i++){
if(s[i]==s[i+t])continue;
else {
cout<<"No"<<endl;
break;
}
}
if(i==b1)cout<<"Yes"<<endl;
}
}
算法2
(哈希表)
时间复杂度:每一个询问的时间复杂度为O(1)
C++ 代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
int main(){
int n,m;
cin>>n>>m;
// vector<ull>arr(n);
// vector<ull>p(n);
ull arr[n+1];
ull p[n+1];
// vector<char>s(n);
// cin>>s+1;
char s[n+1];
cin>>s+1;
arr[0]=0;
p[0]=1;
for(int i=1;i<=n;i++){
arr[i]=arr[i-1]*131+s[i];
p[i]=p[i-1]*131;
}//询问前处理好了,询问时可以直接使用,不用向暴力那样一个个遍历。
while(m--){
int l1,r1,l2,r2;
cin>>l1>>r1>>l2>>r2;
if(arr[r1]-arr[l1-1]*p[r1-l1+1]==arr[r2]-arr[l2-1]*p[r2-l2+1])cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}