题解 CF1207G Indie Album
CF1207G Indie Album
题意简述:有
n 种操作,给出整数,整数和字符op,j(op=2),c 。若op=1 则s_i=c ;否则s_i=s_j+c 。m 次询问给出i,t ,求t 在s_i 中的出现次数。本文节选自 ACAM 乱做 IV.
以前打过这场比赛,要是我当时会 ACAM 多好啊。
注意到如果我们对操作串
可是
时间复杂度
/*
Powered by C++11.
Author : Alex_Wei.
*/
#include <bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(3)
//#define int long long
#define pb emplace_back
const int N=4e5+5;
int n,m,ans[N];
int cnt,dn,son[N][26],ed[N],fa[N],sz[N],dfn[N];
vector <int> e[N],f[N],ft[N];
char ad[N];
void ins(int id,string s){
int p=0;
for(char it:s){
if(!son[p][it-'a'])son[p][it-'a']=++cnt;
p=son[p][it-'a'];
} ed[id]=p;
} void build(){
queue <int> q;
for(int i=0;i<26;i++)if(son[0][i])q.push(son[0][i]);
while(!q.empty()){
int t=q.front(); q.pop();
for(int i=0;i<26;i++)
if(son[t][i])q.push(son[t][i]),fa[son[t][i]]=son[fa[t]][i];
else son[t][i]=son[fa[t]][i];
ft[fa[t]].pb(t);
}
} void dfs(int id){
dfn[id]=++dn,sz[id]=1;
for(int it:ft[id])dfs(it),sz[id]+=sz[it];
}
int c[N];
void add(int x,int v){while(x<=dn)c[x]+=v,x+=x&-x;}
int query(int x){int ans=0; while(x)ans+=c[x],x-=x&-x; return ans;}
int query(int l,int r){return query(r)-query(l-1);}
void cal(int id,int p){
if(id)p=son[p][ad[id]-'a'],add(dfn[p],1);
for(int it:e[id])ans[it]=query(dfn[ed[it]],dfn[ed[it]]+sz[ed[it]]-1);
for(int it:f[id])cal(it,p);
add(dfn[p],-1);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int tp,p=0; cin>>tp;
if(tp==2)cin>>p;
f[p].pb(i),cin>>ad[i];
} cin>>m;
string q;
for(int i=1,id;i<=m;i++)
cin>>id>>q,e[id].pb(i),ins(i,q);
build(),dfs(0),cal(0,0);
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}