双Hash--兔子与兔子

Posted cutemush

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了双Hash--兔子与兔子相关的知识,希望对你有一定的参考价值。


很久很久以前,森林里住着一群兔子。
有一天,兔子们想要研究自己的DNA序列。
我们首先选取一个好长好长的DNA序列(小兔子是外星生物,DNA序列可能包含26个小写英文字母)。
然后我们每次选择两个区间,询问如果用两个区间里的DNA序列分别生产出来两只兔子,这两个兔子是否一模一样。
注意两个兔子一模一样只可能是他们的DNA序列一模一样。
Input
第一行输入一个DNA字符串S。
第二行一个数字m,表示m次询问。
接下来m行,每行四个数字l1,r1,l2,r2,分别表示此次询问的两个区间,注意字符串的位置从1开始编号。
数据范围
1≤length(S),m≤1000000
Output
对于每次询问,输出一行表示结果。
如果两只兔子完全相同输出Yes,否则输出No(注意大小写)。
Sample Input
aabbaabb
3
1 3 5 7
1 3 6 8
1 2 1 2
Sample Output
Yes
No
Yes?

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
typedef long long ll;
//typedef long double ld;


int n,m;
char s[maxn];

inline int read()
{
    int x=0,f=1; char ch=getchar();
    for (;ch<‘0‘||ch>‘9‘;ch=getchar()) if (ch==‘-‘) f=-1;
    for (;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘;
    return x*f;
}

struct hash_table
{
	int mod,base,power[maxn],h[maxn];
	void build()
	{
		for (int i=1;i<=n;i++) 
		   h[i]=1ll*h[i-1]*base%mod+s[i]-‘a‘;
		power[0]=1; 
		for (int i=1;i<=n;i++) 
		     power[i]=1ll*power[i-1]*base%mod;
	}
	bool check(int l1,int r1,int l2,int r2)
	{
		int len=r1-l1+1;
		int h1=((h[r1]-1ll*h[l1-1]*power[len]%mod)+mod)%mod;
		int h2=((h[r2]-1ll*h[l2-1]*power[len]%mod)+mod)%mod;
		return h1==h2;
	}
}H1,H2;

int main()
{
	H1.mod=998244353,H2.mod=666623333; H1.base=233,H2.base=431;
	scanf("%s",s+1); n=strlen(s+1);
	H1.build(),H2.build();
	int id=0;
	for (int T=read();T;T--)
	{
		++id;
		int l1=read(),r1=read(),l2=read(),r2=read();
		if (r1-l1+1!=r2-l2+1)
		   {
		         puts("No"); 
				 continue;
		   }
		puts((H1.check(l1,r1,l2,r2)&&H2.check(l1,r1,l2,r2))?"Yes":"No");
	}
    return 0;
}

  

单Hash

//19260817
#include<bits/stdc++.h>

using namespace std;
typedef unsigned long long ull;
const int MAX=1000010;
int mod=19260817;
int n,length,q;
int l1,r1,l2,r2;
char a[MAX];
ull sum[MAX];
ull prime=131;
ull power[MAX];
ull cut(int l,int r) 
{
	return ((sum[r]-sum[l-1]*power[r-l+1])%mod+mod)%mod;
}
int main() {
	scanf("%s",a+1);
	scanf("%d",&q);
	int num=strlen(a+1);
	power[0]=1;
	sum[0]=0;
	for(int i=1; i<=1000000; i++)         
	power[i]=(power[i-1]*prime)%mod;
	for(int i=1; i<=num; i++)         
	sum[i]=(sum[i-1]*prime+a[i]-‘a‘)%mod;
	while(q--)     
	{
		scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
		if(l1-r1!=l2-r2) 
		{
			puts("No");
			continue;
		}
		if(cut(l1, r1)==cut(l2, r2))puts("Yes");
		else puts("No");
	}
	return 0;
}

  

以上是关于双Hash--兔子与兔子的主要内容,如果未能解决你的问题,请参考以下文章

兔子与兔子(字符串Hash)

AcWing:138. 兔子与兔子(Hash)

CH 1401 - 兔子与兔子 - [字符串hash]

CHOI 1401 兔子与兔子

C语言100个经典算法源码片段

哈希兔子与兔子