造一个广义后缀自动机,LCT维护即可,询问1可以在插入的时候直接维护
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 200010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
struct vec{
int to;
int fro;
int v;
};
struct LCT{
int fa[MAXN],son[MAXN][2],sum[MAXN],ch[MAXN];
int st[MAXN],tp;
inline bool ir(int x){
return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
}
inline void cot(int x,int y,int z){
if(x){
fa[x]=y;
}
if(y){
son[y][z]=x;
}
}
inline void rot(int x,bool z){
int xx=fa[x],xxx=fa[xx];
cot(son[x][z],xx,z^1);
if(!ir(xx)){
cot(x,xxx,son[xxx][1]==xx);
}else{
fa[x]=xxx;
}
cot(xx,x,z);
}
inline void toch(int x,int y){
if(!x){
return ;
}
sum[x]+=y;
ch[x]+=y;
}
inline void pd(int x){
toch(son[x][0],ch[x]);
toch(son[x][1],ch[x]);
ch[x]=0;
}
void splay(int x){
st[++tp]=x;
for(int i=x;!ir(i);i=fa[i]){
st[++tp]=fa[i];
}
for(;tp;tp--){
pd(st[tp]);
}
int xx=fa[x],xxx=fa[xx];
while(!ir(x)){
if(ir(xx)){
rot(x,son[xx][0]==x);
}else{
bool z=son[xxx][0]==xx;
if(son[xx][z]==x){
rot(x,z^1);
rot(x,z);
}else{
rot(xx,z);
rot(x,z);
}
}
xx=fa[x];
xxx=fa[xx];
}
}
void acs(int x){
int t=0;
while(x){
splay(x);
son[x][1]=t;
t=x;
x=fa[x];
}
}
void cut(int x){
acs(x);
splay(x);
fa[son[x][0]]=0;
son[x][0]=0;
}
void link(int x,int y){
cut(x);
fa[x]=y;
}
int ask(int x){
acs(x);
splay(x);
return sum[x];
}
};
LCT T;
vec mp[MAXN*2];
int tai[MAXN],cnt;
int n,m;
char s[MAXN];
int mx[MAXN*2],fa[MAXN*2],son[MAXN*2][3];
int lst[MAXN],tot,rt;
bool vis[MAXN];
ll ans;
inline void be(int x,int y,int z){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
mp[cnt].v=z;
}
inline void bde(int x,int y,int z){
be(x,y,z);
be(y,x,z);
}
int ins(int x,int lst){
int p=lst,np=++tot;
mx[np]=mx[p]+1;
while(p&&(!son[p][x])){
son[p][x]=np;
p=fa[p];
}
if(!p){
fa[np]=rt;
T.link(np,rt);
ans+=mx[np]-mx[fa[np]];
}else{
int q=son[p][x];
if(mx[q]==mx[p]+1){
fa[np]=q;
T.link(np,q);
ans+=mx[np]-mx[fa[np]];
}else{
int nq=++tot;
mx[nq]=mx[p]+1;
memcpy(son[nq],son[q],sizeof(son[q]));
T.link(nq,fa[q]);
fa[nq]=fa[q];
ans+=mx[nq]-mx[fa[nq]];
ans-=mx[q]-mx[fa[q]];
T.link(q,nq);
fa[q]=nq;
ans+=mx[q]-mx[fa[q]];
T.link(np,nq);
fa[np]=nq;
ans+=mx[np]-mx[fa[np]];
T.acs(nq);
T.splay(nq);
T.sum[nq]=T.sum[q];
while(p&&son[p][x]==q){
son[p][x]=nq;
p=fa[p];
}
}
}
T.acs(np);
T.splay(np);
T.toch(np,1);
return np;
}
void dfs(int x){
int i,y;
vis[x]=1;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
if(!vis[y]){
lst[y]=ins(mp[i].v,lst[x]);
dfs(y);
}
}
}
char z[MAXN];
int main(){
lst[1]=rt=tot=1;
int i,o,x,y;
scanf("%*d%d",&n);
for(i=1;i<n;i++){
scanf("%d%d%s",&x,&y,z);
bde(x,y,z[0]-'a');
}
dfs(1);
scanf("%d",&m);
while(m--){
scanf("%d",&o);
if(o==1){
printf("%lld\n",ans);
}else if(o==2){
scanf("%d%d",&o,&n);
for(i=1;i<n;i++){
scanf("%d%d%s",&x,&y,z);
bde(x,y,z[0]-'a');
}
dfs(o);
}else{
scanf("%s",z+1);
int p=rt;
int len=strlen(z+1);
bool flag=1;
for(i=1;i<=len;i++){
if(!son[p][z[i]-'a']){
flag=0;
break;
}
p=son[p][z[i]-'a'];
}
if(!flag){
printf("0\n");
}else{
printf("%d\n",T.ask(p));
}
}
}
return 0;
}
/*
1
4
1 2 a
1 3 b
2 4 b
6
1
2 2 4
2 5 b
2 6 c
5 7 b
1
3 ab
2 6 3
6 8 a
6 9 b
1
*/