咱們能夠先把全部s串在AC 自動機上跑一遍,考慮若是一個串出現了,則我所能指向的全部fail節點均可以得到貢獻,因而咱們建出一棵fail樹。c++
接下來考慮把T串加入,本身思考咱們發現若是隻是單純把我到根節點的路徑權值都+1,咱們可能會重複計算答案,因而就要樹鏈合併,即按照dfs序排序後,每一隻修改我和上一個點的lca到個人路徑,就不會重複。有點卡空間,個人作法是lca用線段樹維護區間d最小值找出lca,時間(常數大)換空間了。git
沒有強制在線因此能夠用AC自動機寫,若是強制在線bzoj2555,就只能用數據結構套數據結構維護了,可怕。算法
#include<bits/stdc++.h> #define il inline #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=3e6+5,M=1e5+5; char s[N];queue<int> q; int minn[N<<2],ch[N][26],n,Q,tot=1,head[N],ne[N],to[N],num[N<<1],id[N],kk; int que[N],nt,g[N],d[N],cnt,dfn[N],sz[N],a[N],fail[N],idx; il int read(){int x;char ch;_(!);x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return x;} il void insert(int x,int y){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;} bool cmp(int t1,int t2){return dfn[t1]<dfn[t2];} il void add(int x,int v){for(;x<=tot;x+=x&-x)g[x]+=v;} il int query(int x){int ans=0;for(;x;x-=x&-x)ans+=g[x];return ans;} il int Min(int x,int y){return d[x]<d[y]?x:y;} il int ins(){ int l=strlen(s+1);int x=1; for(int i=1;i<=l;i++){ if(!ch[x][s[i]-'a'])ch[x][s[i]-'a']=++tot; x=ch[x][s[i]-'a']; } return x; } il void dfs(int x){ dfn[x]=++idx;sz[x]=1;num[id[x]=++kk]=x; for(int i=head[x];i;i=ne[i]){ d[to[i]]=d[x]+1;dfs(to[i]); sz[x]+=sz[to[i]];num[++kk]=x; } } il void build(int x,int l,int r){ if(l==r){minn[x]=num[l];return;} int mid=(l+r)>>1; build(x<<1,l,mid);build(x<<1|1,mid+1,r); minn[x]=Min(minn[x<<1],minn[x<<1|1]); } il int qm(int x,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return minn[x]; int mid=(l+r)>>1; if(qr<=mid)return qm(x<<1,l,mid,ql,qr); else if(mid<ql)return qm(x<<1|1,mid+1,r,ql,qr); else return Min(qm(x<<1,l,mid,ql,qr),qm(x<<1|1,mid+1,r,ql,qr)); } il int Lca(int x,int y){ int l=id[x],r=id[y];if(l>r)swap(l,r); return qm(1,1,kk,l,r); } int main() { n=read(); for(int i=1;i<=n;i++){scanf(" %s",s+1);a[i]=ins();} q.push(1); while(!q.empty()){ int x=q.front();q.pop(); for(int i=0;i<26;i++){ if(!ch[x][i])continue; int tmp=fail[x]; while(tmp>1&&!ch[tmp][i])tmp=fail[tmp]; if(ch[tmp][i])fail[ch[x][i]]=ch[tmp][i]; else fail[ch[x][i]]=1;q.push(ch[x][i]); } } for(int i=2;i<=tot;i++)insert(fail[i],i); d[1]=1;dfs(1);build(1,1,kk);int Q=read(); while(Q--){ int op=read(); if(op==1){ scanf(" %s",s+1);int l=strlen(s+1); int x=1,nt=0;que[++nt]=x; for(int i=1;i<=l;i++){ while(x!=1&&!ch[x][s[i]-'a'])x=fail[x]; if(ch[s[i]-'a'])x=ch[x][s[i]-'a'];que[++nt]=x; } sort(que+1,que+1+nt,cmp);add(dfn[que[1]],1); for(int j=2;j<=nt;j++){ add(dfn[que[j]],1); add(dfn[Lca(que[j],que[j-1])],-1); } } else{ int x=a[read()];printf("%d\n",query(dfn[x]+sz[x]-1)-query(dfn[x]-1)); } } return 0; }