Codeforces 1204G-Indie Album

Codeforces 1204G-Indie Album

题意

有n个字符串,对于第i个字符串通过以下两种方式中的一个给出。
1、 1 c,该字符串只含一个字符c。
2、 2 j c,该字符串为第j个字符串末尾添加一个字符c得到。
m次询问,每次询问给出一个整数x和一个字符串s,问在第x个字符串中,字符串s出现了几次。

题解

对于m个询问的字符串,构建AC自动机,利用fail树的性质:将母串在AC自动机上跑一遍并将走到的位置权值+1后,一个字符串在母串中出现的次数就是该字符串所对应的fail节点的子树权值和。
发现给出的n个字符串也是一棵树的形式,所以可以在树上dfs,利用dfs序和树状数组查询fail节点的字数权值和。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
int n,m; 
int fa[N],ans[N];
char s[N],t[N];
int ver[N],head[N],nxt[N],tt;
int tr[N][26],fail[N],tot;
int dfn[N],id,Size[N];
int c[N];

vector<pair<int,int> > que[N];

void add(int u,int v){
	ver[++tt]=v;
	nxt[tt]=head[u];head[u]=tt;
}

int insert(char *s,int len){
	int u=0;
	for(int i=1;i<=len;i++){
		int ch=s[i]-'a';
		if(!tr[u][ch]) tr[u][ch]=++tot;
		u=tr[u][ch];
	}
	return u;
} 

queue<int> q;
vector<int> E[N];
void build(){
	for(int i=0;i<26;i++){
		if(tr[0][i]) q.push(tr[0][i]);
	}
	while(q.size()){
		int u=q.front();q.pop();
		E[fail[u]].push_back(u);
		for(int i=0;i<26;i++){
			if(tr[u][i]){
				fail[tr[u][i]]=tr[fail[u]][i];
				q.push(tr[u][i]);
			}else tr[u][i]=tr[fail[u]][i];
		}
	}
}

void AC_dfs(int u){
	int k=E[u].size();
	dfn[u]=++id;
	Size[u]=1;
	for(int i=0;i<k;i++){
		int v=E[u][i];
		AC_dfs(v);
		Size[u]+=Size[v];
	}
}

void update(int x,int y){
	for(;x<=id;x+=(x&-x)) c[x]+=y;
}

int query(int x){
	int ans=0;
	for(;x;x-=(x&-x)) ans+=c[x];
	return ans;
}

int solve(int x){
	return query(dfn[x]+Size[x]-1)-query(dfn[x]-1);
}

void dfs(int x,int u){
	int ch=s[x]-'a';
	u=tr[u][ch];
	update(dfn[u],1);
	for(int i=head[x];i;i=nxt[i]){
		int v=ver[i];
		dfs(v,u);
	}
	int k=que[x].size();
	for(int i=0;i<k;i++){
		ans[que[x][i].second]=solve(que[x][i].first);
	}
	update(dfn[u],-1);
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int op,x;
		scanf("%d",&op);
		if(op==2){
			scanf("%d",&x);
			fa[i]=x;
		}
		add(fa[i],i);
		scanf("%s",&s[i]);
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int idx;
		scanf("%d",&idx);
		scanf("%s",t+1);
		int len=strlen(t+1);
		int e=insert(t,len);
		que[idx].push_back(make_pair(e,i));
	}
	build();
	AC_dfs(0);
	for(int i=1;i<=n;i++){
		if(!fa[i]) dfs(i,0);
	}
	for(int i=1;i<=m;i++){
		printf("%d\n",ans[i]);
	}
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/qjy73/p/12549046.html