1. 程式人生 > >【BZOJ4943】【NOI2017】蚯蚓排隊(雜湊)

【BZOJ4943】【NOI2017】蚯蚓排隊(雜湊)

題面

BZOJ
洛谷
UOJ

題解

記得去年看網路同步賽的時候是一臉懵逼的。
昨天看到zsy做了,今天就看了看。。
這不是Hash的傻逼題嗎。。。
嗚。。。
開連結串列存一下前驅後繼,因為詢問長度不超過50
那麼,總的串的個數不超過50n,暴力hash一下然後拿雜湊表存一下就好了。
我開始用的map然後TLE飛了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define ull unsigned long long #define ll long long #define RG register #define MAX 222222 #define MOD 998244353 const int base=233; inline int read() { RG int x=0,t=1
;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } char ch[10000010]; ull pw[MAX],has[MAX]; int nt[MAX],lt[MAX],a[MAX],g[MAX<<1]; int n,m; const int
mod=7654321; struct Hash_Table { int h[mod],cnt;struct Line{int len,next,w;ull s;}e[10000000]; void Add(int len,ull s,int w) { int u=s%mod; for(int i=h[u];i;i=e[i].next) if(e[i].len==len&&e[i].s==s) {e[i].w=(e[i].w+w)%MOD;return;} e[++cnt]=(Line){len,h[u],w,s};h[u]=cnt; } int Query(int len,ull s) { int u=s%mod; for(int i=h[u];i;i=e[i].next) if(e[i].len==len&&e[i].s==s) return e[i].w; return 0; } }Hash; void Link(int x,int y) { nt[x]=y;lt[y]=x; ull ls=0;int tot=0; for(int i=x,len=49;i&&len;i=lt[i],--len) { ull s=0;ls+=a[i]*pw[tot++];s=ls;int l=tot+1; for(int j=y;j&&l<=50;j=nt[j],++l)s=s*base+a[j],Hash.Add(l,s,1); } } void Cut(int x) { int y=nt[x];ull ls=0;int tot=0; for(int i=x,len=49;i&&len;i=lt[i],--len) { ull s=0;ls+=a[i]*pw[tot++];s=ls;int l=tot+1; for(int j=y;j&&l<=50;j=nt[j],++l)s=s*base+a[j],Hash.Add(l,s,MOD-1); } nt[x]=lt[y]=0; } int Query(int len) { int l=strlen(ch+1),ret=1;ull s=0; for(int i=1;i<len;++i)s=s*base+ch[i]-48; ch[0]='0'; for(int i=len;i<=l;++i) { s=s*base+ch[i]-48; s-=pw[len]*(ch[i-len]-48); ret=1ll*ret*Hash.Query(len,s)%MOD; } return ret; } int main() { pw[0]=1;for(int i=1;i<MAX;++i)pw[i]=pw[i-1]*base; n=read();m=read(); for(int i=1;i<=n;++i)Hash.Add(1,a[i]=read(),1); while(m--) { int opt=read(); if(opt==1) { int x=read(),y=read(); Link(x,y); } else if(opt==2){Cut(read());} else { scanf("%s",ch+1);int k=read(); printf("%d\n",Query(k)); } } return 0; }