为什么我觉得T2比T1裸啊
突破口是\(k\leq 50\),我们可以直接维护当前串长\(\leq k\)的所有子串的\(hash\)值,那么\(3\)操作的时间复杂度变成了\(O(\sum|S|)\)
考虑如何维护\(1,2\)操作(其实1操作对此的暗示也十分明显),我们通过维护一个链表来进行快速合并和断开,每次合并或断开的时候直接\(O(k^2)\)维护\(hash\)值的增减,冷静分析一下的话发现时间复杂度其实应该是\(O((n+c)k^2)\)的,并且很明显那个\(k^2\)是跑不满的
其实还是比较好写的
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef unsigned long long ull;
const int N=200000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define p 10000009
#define bas 7
#define eps 1e-8
#define K 50
struct node{
int cnt,nxt;ull val;
}hsh[20020000];
int all=0,head[p+10];
int n,m,num[200200],pre[200200],suf[200200];
ull pw[200200];
char s[10000200];
int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
void insert(ull x,int val)
{
int u=x%p,i;
for (i=head[u];i;i=hsh[i].nxt)
{
if (hsh[i].val==x)
{
hsh[i].cnt+=val;
return;
}
}
hsh[++all].val=x;hsh[all].cnt=val;hsh[all].nxt=head[u];head[u]=all;
}
int query(ull x)
{
int i,u=x%p;
for (i=head[u];i;i=hsh[i].nxt)
{
if (hsh[i].val==x) return hsh[i].cnt;
}
return 0;
}
int main()
{
n=read();m=read();
pw[0]=1;
rep(i,1,N) pw[i]=pw[i-1]*bas;
rep(i,1,n)
{
num[i]=read();
insert(num[i],1);
}
while (m--)
{
int op=read();
if (op==1)
{
int x=read(),y=read();
pre[y]=x;suf[x]=y;
int i,pcnt=1;ull now=0;
for (i=x;i && pcnt<=K;i=pre[i],pcnt++)
{
now+=(pw[pcnt-1]*num[i]);
ull tmp=now;int j,tot=pcnt+1;
for (j=y;j && tot<=K;j=suf[j],tot++)
{
tmp=tmp*bas+num[j];
insert(tmp,1);
}
}
}
else if (op==2)
{
int x=read(),y=suf[x];
pre[y]=0;suf[x]=0;
int i,pcnt=1;ull now=0;
for (i=x;i && pcnt<=K;i=pre[i],pcnt++)
{
now+=(pw[pcnt-1]*num[i]);
ull tmp=now;int j,tot=pcnt+1;
for (j=y;j && tot<=K;j=suf[j],tot++)
{
tmp=tmp*bas+num[j];
insert(tmp,-1);
}
}
}
else
{
scanf("%s",s+1);
int k=read(),len=strlen(s+1);
ull now=0;ll ans=1;
rep(i,1,len)
{
//cout << now << endl;
now=now*bas+(s[i]-'0');
//cout << now << endl;
if (i>=k)
{
ans=ans*query(now)%maxd;
now-=((s[i-k+1]-'0')*pw[k-1]);
}
//cout << now << endl << endl;
}
printf("%lld\n",ans);
}
}
return 0;
}
/*
5 9
3 1 3 5 3
3 333135 2
3 333135 1
1 1 3
1 2 5
1 3 2
1 5 4
3 333135 2
3 333135 1
3 333135 3
*/