bzoj 3207(主席树+hash)

传送门
问题:给定一个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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值