传送门 问题:给定一个n个数的序列,对于m次询问,回答[l,r]这个区间内是否有一个长度为k(固定)的子串Si。
先将字符串哈希,再扔进主席树维护即可,注意unsigned long long。这大概是本蒟蒻第一次写哈希套其它数据结构,如果代码有不严谨之处请大神多多指教。
#include<bits/stdc++.h> #define base 223 using namespace std; const int maxn=2e5+2; const int maxm=maxn*20; typedef unsigned long long ull; int n,m,k; map<ull,int> mp;int cnt=0; ull h[maxn],p[maxn]; int a[maxn],root[maxn],lc[maxm],rc[maxm],siz[maxm],tim=0; inline int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x*f; } void insert(int pre,int &now,int l,int r,int val) { now=++tim,siz[now]=siz[pre]+1; if (l==r) return ; lc[now]=lc[pre],rc[now]=rc[pre]; int mid=(l+r)>>1; if (val<=mid) insert(lc[pre],lc[now],l,mid,val); else insert(rc[pre],rc[now],mid+1,r,val); } bool query(int pre,int now,int l,int r,int val) { if (l==r) return siz[now]>siz[pre]; int mid=(l+r)>>1; if (val<=mid) return query(lc[pre],lc[now],l,mid,val); else return query(rc[pre],rc[now],mid+1,r,val); } int main() { // freopen("bzoj 3207.in","r",stdin); n=read(),m=read(),k=read(); h[0]=0; for (register int i=1;i<=n;++i) h[i]=h[i-1]*base+read(); p[0]=1; for (register int i=1;i<=k;++i) p[i]=p[i-1]*base; for (register int i=k;i<=n;++i) { ull tmp=h[i]-h[i-k]*p[k]; if (!mp[tmp]) mp[tmp]=++cnt; a[i]=mp[tmp]; } memset(root,0,sizeof(root)); for (register int i=k;i<=n;++i) insert(root[i-1],root[i],1,n,a[i]); while (m--) { int x=read(),y=read(); ull tmp=0; for (int i=1;i<=k;++i) tmp=tmp*base+read(); if (x+k-1>y||!mp[tmp]) {puts("Yes");continue;} puts(query(root[x+k-2],root[y],1,n,mp[tmp])?"No":"Yes"); } return 0; }