bzoj3207花神的嘲讽计划Ⅰ

题意:http://www.lydsy.com/JudgeOnline/problem.php?id=3207

   给定一个原字符串和m个询问,每次查询原字符串[l,r]内是否包含给定字符串s (len(s)<=20且len(s)相同)

sol  :考虑hash,将原串没len(s)位hash一次放入桶中,再将每次询问hash后在桶中查询(感觉很像rk-hash)

   因为每次[l,r]转移到[l,r±1]、[l±1,r]都是从桶中取出or放入一个数,复杂的O(1),可以使用莫队算法

   P.S.需要离散化而不能取模,否则memset复杂度爆炸

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define int long long
using namespace std;
const int Mx=100010;
const int p=23333333LL;
struct Node { int x,y,val,num; } str[Mx];
bool cmp1 (Node a,Node b) { return a.x<b.x; }
bool cmp2 (Node a,Node b) { return a.y<b.y; }
int n,m,k,temp,a[Mx],h[Mx],ton[p+10],ans[Mx];
signed main()
{
    scanf("%lld%lld%lld",&n,&m,&k);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=1;i<=m;i++)
    {
        int Tmp[50],tmp=1;str[i].num=i;
        scanf("%lld%lld",&str[i].x,&str[i].y);
        for(int j=1;j<=k;j++) scanf("%lld",&Tmp[j]);
        for(int j=k;j>=1;j--) str[i].val+=tmp*Tmp[j],tmp*=37,tmp%=p,str[i].val%=p;
        if(i==1) temp=tmp/37;
    }
    for(int i=k,tmp=1;i>=1;i--) h[1]+=tmp*a[i],tmp*=37,tmp%=p,h[1]%=p;
    for(int i=k+1;i<=n;i++) h[i-k+1]=(((h[i-k]-(a[i-k]*temp))*37+a[i])%p+p)%p;
    sort(str+1,str+1+m,cmp1);
    for(int i=1;i<=m;i+=sqrt(m)) sort(str+i,str+min(m,i+(int)sqrt(m)),cmp2);
    for(int i=1;i<=m;i++)
    {
        if(i%(int)sqrt(m)==1||i==1)
        {
            memset(ton,0,sizeof(ton));
            for(int j=str[i].x;j<=str[i].y;j++) ton[(h[j]%p+p)%p]++;
        }
        else
        {
            for(int j=str[i-1].x,to=str[i].x;j!=to;)
            {
                if(j<to) ton[(h[j]%p+p)%p]--,j++;
                else j--,ton[(h[j]%p+p)%p]++;
            }
            for(int j=str[i-1].y,to=str[i].y;j!=to;)
            {
                if(j<to) j++,ton[(h[j-k]%p+p)%p]++;
                else ton[(h[j-k]%p+p)%p]--,j--;
            }
        }
        ans[str[i].num]=ton[str[i].val];
    }
    for(int i=1;i<=m;i++)
    {
        if(ans[i]==0) puts("Yes");
        else puts("No");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xiaoxubi/p/6336616.html