测试地址:蚯蚓排队
做法:本题需要用到链表+字符串哈希。
因为很小,所以用链表维护队列的形态,每次连接或断开暴力添加新增的子串信息即可,用字符串哈希来加速字符串的匹配即可。
根据一些神奇的复杂度分析,时间复杂度应该是,但是因为我太菜,最后一个点TLE+WA(分点测试TLE,BZOJ上WA),实在是没有办法了,先丢在这里吧……
以下是本人代码:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll mod=998244353;
const ll hashsiz=200003;
const ll Base=131;
int n,m,pre[200010],nxt[200010];
int first[hashsiz+10][51]={0},hashnxt[hashsiz+10][51],hashtot[51]={0};
ll bas[55],a[200010],hashlist[hashsiz+10][51],hashcnt[hashsiz+10][51];
char s[10000010];
ll hashfind(ll x,int k)
{
ll pos=first[x%hashsiz][k];
while(pos&&hashlist[pos][k]!=x) pos=hashnxt[pos][k];
if (!pos) return -1;
return pos;
}
void hashinsert(ll x,int k,ll cnt)
{
ll pos=hashfind(x,k);
if (pos!=-1) hashcnt[pos][k]+=cnt;
else
{
hashlist[++hashtot[k]][k]=x;
hashnxt[hashtot[k]][k]=first[x%hashsiz][k];
hashcnt[hashtot[k]][k]=1;
first[x%hashsiz][k]=hashtot[k];
}
}
void maintain(int v,bool type)
{
int nowl=v,nowr;
ll lft=0,rht;
for(int i=0;i<49&&nowl!=-1;i++)
{
lft+=a[nowl]*bas[i];
rht=lft;
nowl=pre[nowl];
nowr=nxt[v];
for(int j=1;j<=50-i-1&&nowr!=-1;j++)
{
rht=rht*Base+a[nowr];
nowr=nxt[nowr];
hashinsert(rht,i+j+1,type?(ll)1:(ll)-1);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
pre[i]=nxt[i]=-1;
hashinsert(a[i],1,1);
}
bas[0]=1;
for(int i=1;i<=55;i++)
bas[i]=bas[i-1]*Base;
for(int i=1;i<=m;i++)
{
int op,x,y;
scanf("%d",&op);
if (op==1)
{
scanf("%d%d",&x,&y);
nxt[x]=y,pre[y]=x;
maintain(x,1);
}
if (op==2)
{
scanf("%d",&x);
maintain(x,0);
pre[nxt[x]]=-1,nxt[x]=-1;
}
if (op==3)
{
scanf("%s%d",s,&x);
int len=strlen(s);
ll f=0,ans=1;
for(int j=0;j<x-1;j++)
f=f*Base+(ll)(s[j]-'0');
for(int j=x-1;j<len;j++)
{
f=f*Base+(ll)(s[j]-'0');
if (j-x>=0) f-=(ll)(s[j-x]-'0')*bas[x];
int pos=hashfind(f,x);
if (pos!=-1) ans=(ans*hashcnt[pos][x])%mod;
else {ans=0;break;}
}
printf("%lld
",ans);
}
}
return 0;
}