传送门
题解:
对 S S S建立AC自动机之后,我们发现一个 P P P串扔进来就是把所有自己匹配点的祖先不重复地+1,显然树上差分搞定,用树状数组维护一下标记之和就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int get_s(char *s){
int len=0;char c;
while(isspace(c=gc()));
while(s[len++]=c,!isspace(c=gc())&&c!=EOF);
s[len]='\0';return len;
}
template<typename T>
inline T get(){
char c;T num;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int gi(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
cs int N=2e6+7;
char s[N];int len;
int ps[N];
int son[N][26],fa[N],tot;
inline void ins(int id){
len=get_s(s);int u=0;
for(int re i=0;i<len;++i){
int c=s[i]-'a';
if(!son[u][c])son[u][c]=++tot;
u=son[u][c];
}ps[id]=u;
}
int el[N],nxt[N];
inline void adde(int u,int v){nxt[v]=el[u],el[u]=v;}
inline void build(){
std::queue<int> q;
for(int re i=0;i<26;++i)if(son[0][i])q.push(son[0][i]);
while(!q.empty()){
int u=q.front();q.pop();adde(fa[u],u);
for(int re i=0;i<26;++i)
son[u][i]?(q.push(son[u][i]),fa[son[u][i]]=son[fa[u]][i]):(son[u][i]=son[fa[u]][i]);
}
}
int in[N],out[N],siz[N],d[N],ch[N],top[N],nd[N],dfn;
void dfs1(int u){
siz[u]=1;ch[u]=-1;
for(int re v=el[u];v;v=nxt[v]){
d[v]=d[u]+1;dfs1(v);siz[u]+=siz[v];
if(!~ch[u]||siz[ch[u]]<siz[v])ch[u]=v;
}
}
void dfs2(int u,int tp){
top[u]=tp;nd[in[u]=++dfn]=u;
if(~ch[u])dfs2(ch[u],tp);
for(int re v=el[u];v;v=nxt[v])if(v!=ch[u])dfs2(v,v);
out[u]=dfn;
}
inline int LCA(int u,int v){
while(top[u]!=top[v])d[top[u]]>d[top[v]]?u=fa[top[u]]:v=fa[top[v]];
return d[u]<d[v]?u:v;
}
int tr[N];
inline void add(int p,int v){for(;p;p^=p&-p)tr[p]+=v;}
inline int query(int p){int res=0;for(;p<=dfn;p+=p&-p)res+=tr[p];return res;}
inline int qy(int u){return query(in[u])-query(out[u]+1);}
signed main(){
#ifdef zxyoi
freopen("Divljak.in","r",stdin);
#endif
int n=gi();
for(int re i=1;i<=n;++i)ins(i);
build();dfs1(0),dfs2(0,0);
int q=gi();while(q--){
switch(gi()){
case 1:{
len=get_s(s+1);int u=0;
static int vl[N];
for(int re i=1;i<=len;++i)
vl[i]=in[u=son[u][s[i]-'a']];
std::sort(vl+1,vl+len+1);
add(vl[1],1);
for(int re i=2;i<=len;++i){
add(vl[i],1);
if(i!=1)add(in[LCA(nd[vl[i-1]],nd[vl[i]])],-1);
}
break;
}
case 2:cout<<qy(ps[gi()])<<"\n";break;
}
}
return 0;
}