校内测 11.26 T1 询问【字母串】


题目:

传送门


题意:

定义两个字符串等价,当且仅当一个串中的 26 26 26中字母在对应各不相同的 26 26 26中字母后和另一个串相同
给出一个原串 s s s,有 m m m组形如 ( x , y , z ) (x,y,z) (x,y,z)的询问,表示从 x x x y y y开始,长度为 z z z s s s的两个子串是否等价


分析:

对于两个串是否等价,我们不难发现,只有当字母的排列相同时才有可能,还要保证每种字母对应的是不同的字母
所以我们可以想想如何去记录这样的东西,这,似乎是一种状态,那我们对于字符串每个字母单独记录
一个位置上是不是这种字母,用 1 / 0 1/0 1/0来表示,随便给个进制,状态就是把整个串的 1 / 0 1/0 1/0乘在一起,形如 10010011 10010011 10010011,当然具体的情况还是要看进制的(十进制被卡了我也不晓得为什么)
对于两个子串等价的判定,我们根据每种字母的状态,因为我们只关心这种字母的排列情况,而变成了什么字母并不影响答案的判定,所以把所有状态排个序,逐个比较


代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
#define bace 200005
#define U unsigned
using namespace std;
inline LL read()
{
	LL s=0,f=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9') {s=s*10+c-'0';c=getchar();}
	return s*f;
}
char s[200005];
int t[200005][30];
U LL M[200005];
U LL ksm(U LL x,U LL y)
{
	U LL s;
	while(y)
	{
		if(y&1) s*=x;
		x*=x;y>>=1;
	}
	return s;
}
int q1[30],q2[30];
int main()
{
//	freopen("data.in","r",stdin);
//	freopen("1.out","w",stdout);
	int n=read(),m=read();
	scanf("%s",s+1);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=26;j++) t[i][j]=t[i-1][j];
		t[i][s[i]-'a'+1]++;
	}
	for(int i=1;i<=n;i++)
	{
		M[i]=M[i-1];M[i]=(U LL)M[i]*bace+1;
		int k=i+1,l=1;
		while(s[k]==s[k-1])
		{
			M[k]=M[i-1];l++;
			M[k]=(U LL)M[k]*bace+l;
			k++;
		}
	}
	for(int i=1;i<=m;i++)
	{
		int x=read(),y=read(),z=read();
		int a=x+z-1,b=y+z-1;
		for(int k=1;k<=26;k++)
		{
			q1[k]=t[a][k]-t[x-1][k];
			q2[k]=t[b][k]-t[y-1][k];
		}
		sort(q1+1,q1+27);sort(q2+1,q2+27);
		int tf=0;
		for(int k=1;k<=26;k++) if(q1[k]!=q2[k]) {tf=1;break;}
		if(tf) {printf("NO\n");continue;}
		U LL bc=ksm(bace,z);
		U LL s1=M[a]-M[x-1]*bc,s2=M[b]-M[y-1]*bc;
		if(s1==s2) printf("YES\n"); else printf("NO\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值