之前就写过一遍,今天却写挂了,查了半天发现是数组名写错啦$qwq$
观察到$K$很小,所以使得我们可以哈希(怎么什么都能哈希$qwq$)。我们把长度小于等于$50$的子串扔到哈希表里,并统计出现次数,注意每次合并和分离时,只加入或删除与断开点距离小于等于$50$的;因为其他子串长度太长,或是已经在前几次中被添加在哈希表里了。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<cctype> #include<cstdlib> #include<vector> #include<queue> #include<map> #include<set> #define ll long long #define ull unsigned long long #define R register int using namespace std; namespace Fread { //static char B[1<<15],*S=B,*D=B; //#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++) inline int g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } }using Fread::g; const int N=250000,K=51,mod=998244353,M=19260817,B=11,S=10000010; int n,m,q,a[N],pre[N],nxt[N],cnt[N],s[(K<<1)+10]; ull t[S],p[K<<1]; namespace HASH { struct node { ull vl; int cnt,nxt; node(){} node(ull v,int c,int n) {vl=v,cnt=c,nxt=n;} }h[25000010]; int fir[M],cnt=0; inline void add(ull x,int d) { R st=x%M; for(R i=fir[st];i;i=h[i].nxt) if(h[i].vl==x){ h[i].cnt+=d; return ; } h[++cnt]=node(x,d,fir[st]),fir[st]=cnt; } inline int query(ull x) { R st=x%M; for(R i=fir[st];i;i=h[i].nxt) if(h[i].vl==x) return h[i].cnt; return 0; } inline void merge() { R x=g(),y=g(); memset(s,0,sizeof(s)); R l=K,r=l-1; for(R i=x;i&&l>1;i=pre[i]) s[--l]=a[i]; for(R i=y;i&&r+1<(K<<1);i=nxt[i]) s[++r]=a[i]; for(R i=1;i<=r;++i) t[i]=t[i-1]*B+s[i]; for(R i=l;i<K;++i) for(R j=K;j<=r;++j) add(t[j]-t[i-1]*p[j-i+1],1); nxt[x]=y,pre[y]=x; } inline void div() { R x=g(),y=nxt[x]; memset(s,0,sizeof(s)); R l=K,r=l-1; for(R i=x;i&&l>1;i=pre[i]) s[--l]=a[i]; for(R i=y;i&&r+1<(K<<1);i=nxt[i]) s[++r]=a[i]; for(R i=1;i<=r;++i) t[i]=t[i-1]*B+s[i]; for(R i=l;i<K;++i) for(R j=K;j<=r;++j) add(t[j]-t[i-1]*p[j-i+1],-1); nxt[x]=pre[y]=0; } } char str[11000000]; inline ll query() { register ull vl=0; scanf("%s",str+1); R k=g(),n=strlen(str+1); register ll ans=1; if(k==1) for(R i=1;str[i];++i) ans=(ans*cnt[str[i]-'0'])%mod; else { for(R i=1;str[i];++i) t[i]=t[i-1]*B+str[i]-'0'; for(R i=k;str[i];++i) ans=(ans*HASH::query(t[i]-t[i-k]*p[k]))%mod; } return ans; } signed main() { #ifdef JACK freopen("NOIPAK++.in","r",stdin); #endif n=g(),q=g(); p[0]=1; for(R i=1;i<K;++i) p[i]=p[i-1]*B; for(R i=1;i<=n;++i) a[i]=g(),++cnt[a[i]]; while(q--) { R k=g(); if(k==1) HASH::merge(); else if(k==2) HASH::div(); else printf("%lld ",query()); } }