题目描述
很久很久以前,森林里住着一群兔子。有一天,兔子们想要研究自己的 DNA 序列。我们首先选取一个好长好长的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 个小写英文字母),然后我们每次选择两个区间,询问如果用两个区间里的 DNA 序列分别生产出来两只兔子,这两个兔子是否一模一样。注意两个兔子一模一样只可能是他们的 DNA 序列一模一样。
输入
第一行一个 DNA 字符串 S。
接下来一个数字 m,表示 m 次询问。
接下来 m 行,每行四个数字 l1, r1, l2, r2,分别表示此次询问的两个区间,注意字符串的位置从1开始编号。
其中 1 ≤ length(S), m ≤ 1000000输出
对于每次询问,输出一行表示结果。如果两只兔子完全相同输出 Yes,否则输出 No(注意大小写)
样例输入 Copy
aabbaabb 3 1 3 5 7 1 3 6 8 1 2 1 2样例输出 Copy
Yes No Yes
字符串哈希:将一个字符串通过一种映射关系(字符串到p进制数,p一般取131或1331)转化为一个整数,通过整数对比来反映字符串关系
代码
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long llu; //利用llu的自然溢出,相当于mod2^64;
const int N = 1000010,base = 131; //取131冲突小,也可以取1331;
char str[N];
llu h[N],p[N]; //h[i]记录字符串前缀哈希值,p[i]记录base^i;
llu calculate(int l,int r)
{
return h[r]-h[l-1]*p[r-l+1]; //l到r的子串的哈希值
}
inline int read(){
int num=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9')
num=num*10+c-'0', c=getchar();
return num;
}
int main()
{
int m,l;
scanf("%s",str+1);
l=strlen(str+1);
p[0]=1;
for(int i=1;i<=l;i++){
h[i]=h[i-1]*base+str[i]-'a'+1;
p[i]=p[i-1]*base;
}
cin>>m;
while(m--){
int l1,l2,r1,r2;
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
if(calculate(l1,r1)==calculate(l2,r2)) puts("Yes");
else puts("No");
}
return 0;
}
前面写成 for(i=1;i<=strlen(str+1);i++) 一直TLE,原来for循环每次都会算strlen(),切记