bzoj4943: [Noi2017]蚯蚓

hash表的技能点没有点。。。

作为一名在竞赛室苟延残喘的陪练有点说不过去吧。。。

需要注意的是如果要hash里面断链要考虑头和尾

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef unsigned long long uLL; 
const int _=1e2;
const int maxn=2*1e5+_;
const int maxm=3*1e5+_;
const int maxK=50+5;
const int maxH=1.1*1e7;
const int mins=1.5*1e7+_;
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void write(int x)
{
    if(x>=10)write(x/10);
    putchar(x%10+'0');
}

//--------------------------------------------------------------------------------

const uLL hbase=31; uLL hmi[maxK];//1

const uLL hm=10233333;//2 
struct Hash
{
    int num[mins];uLL d[mins],c[mins];//是向后多少数字串,第一步自然溢出的哈希值是多少 ,出现多少次
    int len,first[maxH],last[maxH],nxt[mins];
    void insert(int w,uLL k)
    {
        int x=k%hm;
        for(int i=first[x];i;i=nxt[i])
            if(num[i]==w&&d[i]==k){c[i]++;return ;}
            
        int now=++len;
        if(last[x]==0)first[x]=last[x]=now;
        else nxt[last[x]]=now,last[x]=now;
        num[now]=w,d[now]=k,c[now]++;
    }
    void erase(int w,uLL k)
    {
        int x=k%hm;
        for(int p=0,i=first[x];i;p=i,i=nxt[i])
            if(num[i]==w&&d[i]==k)
            {
                if(c[i]>1)c[i]--;
                else 
                {
                    if(p==0)first[x]=nxt[i];
                    else nxt[p]=nxt[i];
                    if(last[x]==i)last[x]=p;
                }
                return ;
            }
    }
    uLL getsum(int w,uLL k)
    {
        int x=k%hm;
        for(int i=first[x];i;i=nxt[i])
            if(num[i]==w&&d[i]==k)return c[i];
        return 0;
    }
}H;

//--------------------------------------------------------------------------------

const uLL mod=998244353;
int a[maxn],L[maxn],R[maxn];
char ss[10001000];
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    
    hmi[0]=1;for(int i=1;i<=50;i++)hmi[i]=hmi[i-1]*hbase;
    int n=read(),Q=read();
    for(int i=1;i<=n;i++)
        a[i]=read(),H.insert(1,a[i]);
    
    int op,x,y;
    while(Q--)
    {
        op=read();
        if(op==1)
        {
            x=read(),y=read();
            
            L[y]=x;R[x]=y;
            
            uLL uh=0,vh=0;
            for(int k=x,i=1;k&&i<50;k=L[k],i++)
            {
                uh=uh+a[k]*hmi[i-1];
                vh=uh;
                for(int d=y,j=1;d&&i+j<=50;d=R[d],j++)
                {
                    vh=vh*hbase+a[d];
                    H.insert(i+j,vh);
                }
            }
        }
        else if(op==2)
        {
            x=read(); y=R[x];
            
            uLL uh=0,vh=0;
            for(int k=x,i=1;k&&i<50;k=L[k],i++)
            {
                uh=uh+a[k]*hmi[i-1];
                vh=uh;
                for(int d=y,j=1;d&&i+j<=50;d=R[d],j++)
                {
                    vh=vh*hbase+a[d];
                    H.erase(i+j,vh);
                }
            }
            
            R[x]=L[y]=0; 
        }
        else
        {
            scanf("%s",ss+1);x=read();
            int slen=strlen(ss+1);
            uLL ans=1,uh=0;
            for(int i=1;i<x;i++)uh=uh*hbase+ss[i]-'0';
            for(int i=x;i<=slen;i++)
            {
                uh=uh*hbase+ss[i]-'0';
                ans=(ans*H.getsum(x,uh))%mod;
                uh-=hmi[x-1]*(ss[i-x+1]-'0');
            }
            printf("%llu\n",ans);
        }
    }
        
    return 0;
}

 

posted @ 2019-03-07 21:09  AKCqhzdy  阅读(129)  评论(0编辑  收藏  举报