正题
题目链接:https://www.luogu.com.cn/problem/U142342?contestId=37784
题目大意
一个字符串,定义两个字符串相似为用一些字母代替相同的字母后可以相同。
如urbbr=groorurbbr=groorurbbr=groor,apple≠abcdeapple\neq abcdeapple=abcde
要求支持询问一个字符串的两个区间是否相似
解题思路
我们每个位置的hashhashhash值维护这个字母距离上一个与它相同的字母的距离,发现如果一个字母在这个区间里第一次出现,那么我们应该把它的hashhashhash值清000,所以我们可以直接枚举区间的第一个字母然后减去它的hashhashhash值即可。
时间复杂度O(26n)O(26n)O(26n)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ull unsigned long long
using namespace std;
const int N=2e5+10;
const ull p=1145141;
int n,m,last[26],nxt[N][26];char s[N];
ull pw[N],h[N],f[N];
int get(int l,int r){ull ans=h[r]-h[l-1]*pw[r-l+1];for(int i=0;i<26;i++){if(nxt[l][i]<0||l+nxt[l][i]>r)continue;ans=ans-f[l+nxt[l][i]]*pw[r-l-nxt[l][i]];}return ans;
}
int main()
{scanf("%d%d",&n,&m);scanf("%s",s+1);pw[0]=1;for(int i=1;i<=n;i++){int c=s[i]-'a';h[i]=h[i-1]*p+(f[i]=i-last[c]);pw[i]=pw[i-1]*p;last[c]=i;}memset(last,0,sizeof(last));for(int i=n;i>=1;i--){last[s[i]-'a']=i;for(int j=0;j<26;j++)nxt[i][j]=last[j]-i;}for(int i=1;i<=m;i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);if(get(x,x+z-1)==get(y,y+z-1))printf("YES\n");else printf("NO\n");}
}