因为k只有50,所以先把所有询问的字符串拆开,加到hash表里,然后用链表模拟整个过程,暴力把新产生的或消失的字符串在hash表里更新答案,复杂度就是对的
具体做法和时间复杂度分析可以看lzz的知乎回答
https://www.zhihu.com/question/62597216
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <assert.h>
#define fi first
#define se second
using namespace std;
typedef unsigned long long Ull;
typedef pair<Ull,int> Ui;
const int N=5e5+10,P=998244353,M=6e6+20,mod=5780347,base=17;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void rea(int &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
inline int rea(int *x){
char c=nc(); int len=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x[len++]=c-'0',c=nc());
return len;
}
inline Ull Pow(Ull x,int y){
Ull ret=1;
for(;y;y>>=1,x=x*x) if(y&1) ret=ret*x;
return ret;
}
struct Hashtable{
int nxt[M],cnt;
struct nodes{
Ui val;
nodes *nxt;
}node[M],*G[M];
Ui notf;
Hashtable(){ cnt=0; notf=Ui(-1,-1);}
Ui *insert(Ull x){
int u=x%mod;
for(nodes *i=G[u];i;i=i->nxt)
if(i->val.fi==x) return &i->val;
int cur=++cnt;
node[cur].val.fi=x; node[cur].val.se=0; node[cur].nxt=G[u]; G[u]=node+cur;
return &node[cur].val;
}
Ui *find(Ull x){
int u=x%mod;
for(nodes *i=G[u];i;i=i->nxt)
if(i->val.fi==x) return &i->val;
return ¬f;
}
}Ht;
struct works{
int type;
vector<Ui*> q;
int bg,ed,k;
int x,y;
}Q[N];
int s[M],lst,cur;
struct A{
int len;
A *nxt,*pre;
}a[N];
int n,m,maxk;
inline void Modify(A *x,A *y,int d){
Ull val=0,prod=1; A *cur=x;
for(int i=1;i<maxk;prod*=base,i++){
val+=prod*cur->len;
Ull key=val; A *now=y;
for(int j=1;j<=maxk-i;j++){
key=key*base+now->len;
Ui *it=Ht.find(key);
if(*it!=Ht.notf) it->second+=d;
if(!now->nxt) break;
now=now->nxt;
}
if(!cur->pre) break;
cur=cur->pre;
}
}
void print(int x){
if(x>=10) print(x/10);
putchar(x%10+'0');
}
int main(){
rea(n); rea(m);
for(int i=1;i<=n;i++) rea(a[i].len);
for(int i=1;i<=m;i++){
rea(Q[i].type);
if(Q[i].type==3){
cur=lst+rea(s+lst); rea(Q[i].k);
maxk=max(maxk,Q[i].k);
Q[i].bg=lst; Q[i].ed=cur;
Ull val=0,pw=Pow(base,Q[i].k);
for(int j=Q[i].bg;j<Q[i].bg+Q[i].k;j++)
val=val*base+s[j];
Q[i].q.push_back(Ht.insert(val));
for(int j=Q[i].bg+Q[i].k;j<Q[i].ed;j++)
val=val*base+s[j]-pw*s[j-Q[i].k],Q[i].q.push_back(Ht.insert(val));
}
else if(Q[i].type==1) rea(Q[i].x),rea(Q[i].y);
else rea(Q[i].x);
}
for(int i=1;i<=n;i++){
Ui *it=Ht.find(a[i].len);
if(*it!=Ht.notf) it->second++;
}
for(int k=1;k<=m;k++){
if(Q[k].type==3){
int ans=1;
for(int j=0;j<Q[k].q.size();j++)
ans=1LL*ans*Q[k].q[j]->se%P;
print(ans); putchar('\n');
//printf("%d\n",ans);
}
else if(Q[k].type==1){
Modify(a+Q[k].x,a+Q[k].y,1);
a[Q[k].x].nxt=a+Q[k].y; a[Q[k].y].pre=a+Q[k].x;
}
else{
Modify(a+Q[k].x,a[Q[k].x].nxt,-1);
a[Q[k].x].nxt=a[Q[k].x].nxt->pre=0;
}
}
return 0;
}