bzoj 3881 - AC自动机 - BIT

题目大意:一开始给定若干字符串。每次往集合中塞一个字符串或者询问开始给定的字符串在多少集合中的串出现过。
题解:显然跑AC自动机,然后在fail树上做链并,这个就按dfs序排序后upd(x,1),upd(lca(x,las),-1)即可,每次询问查子树和即可一个log。
然后……实测每次暴力往上条单词节点跑的非常快,据说可能是根号的复杂度,不是很清楚,总之很难卡。
一个log的:

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define INF (LLONG_MAX/10-10)
#define lint long long
#define N 2000010
#define SIG 26
#define LOG 24
#define db double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct edges{
	int to,pre;
}e[N];int h[N],etop,ps[N];pii p[N];int rt;char s[N];
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
int ch[N][SIG],node_cnt,fail[N],wd[N];
inline int ins(char *s,int n)
{
	int x=rt;
	for(int i=rt,c;i<=n;x=ch[x][c],i++)
		if(!ch[x][c=s[i]-'a']) ch[x][c]=++node_cnt;
	return wd[x]=1,x;
}
inline int get_fail(int rt)
{
	queue<int> q;while(!q.empty()) q.pop();
	rep(i,0,SIG-1) { int &y=ch[rt][i];if(y) q.push(y),fail[y]=rt;else y=rt; }
	while(!q.empty())
	{
		int x=q.front();q.pop();
		rep(i,0,SIG-1)
		{
			int &y=ch[x][i],f=fail[x],c=ch[f][i];
			if(y) fail[y]=c,q.push(y);else y=c;
		}
	}
	rep(i,1,node_cnt) if(fail[i]) add_edge(fail[i],i);
	return 0;
}
#define lb(x) ((x)&-(x))
int b[N];inline int upd(int x,int v) { for(;x<=node_cnt;x+=lb(x)) b[x]+=v;return 0; }
inline int query(int x) { int ans=0;for(;x;x-=lb(x)) ans+=b[x];return ans; }
inline int query(int s,int t) { return query(t)-query(s-1); }
int in[N],out[N],dfc,up[N][LOG],d[N],lst[N],Log[N];
inline int getLCA(int x,int y)
{
	if(d[x]<d[y]) swap(x,y);
	for(int i=Log[d[x]];i>=0;i--)
		if(d[up[x][i]]>=d[y]) x=up[x][i];
	if(x==y) return x;
	for(int i=Log[d[x]];i>=0;i--)
		if(up[x][i]^up[y][i]) x=up[x][i],y=up[y][i];
	return up[x][0];
}
int dfs(int x)
{
	in[x]=++dfc,d[x]=d[up[x][0]]+1;
	rep(i,1,Log[d[x]]) up[x][i]=up[up[x][i-1]][i-1];
	for(int i=h[x],y;i;i=e[i].pre) up[y=e[i].to][0]=x,dfs(y);
	return out[x]=dfc;
}
inline int cmp(int a,int b) { return in[a]<in[b]; }
inline int upd(char *s,int n)
{
	int x=rt,cnt=0;rep(i,1,n) x=ch[x][s[i]-'a'],lst[++cnt]=x;
	if(!cnt) return 0;sort(lst+1,lst+cnt+1,cmp);upd(in[lst[1]],1);
	rep(i,2,cnt) if(lst[i]^lst[i-1]) upd(in[lst[i]],1),upd(in[getLCA(lst[i-1],lst[i])],-1);
	return 0;
}
int main()
{
	int n=inn(),q,x;rt=node_cnt=1;
	rep(i,1,n) scanf("%s",s+1),ps[i]=ins(s,(int)strlen(s+1));
	rep(i,2,node_cnt) Log[i]=Log[i>>1]+1;
	get_fail(rt),d[1]=1,dfs(1),q=inn();
	rep(i,1,q)
		if(inn()==1) scanf("%s",s+1),upd(s,(int)strlen(s+1));
		else x=ps[inn()],printf("%d\n",query(in[x],out[x]));
	return 0;
}

暴力:

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define INF (LLONG_MAX/10-10)
#define lint long long
#define N 2000010
#define SIG 26
#define db double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct edges{
	int to,pre;
}e[N];int h[N],etop,ps[N];pii p[N];int q,rt;char s[N];
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
int ch[N][SIG],node_cnt,fail[N],wd[N];
inline int ins(char *s,int n)
{
	int x=rt;
	for(int i=rt,c;i<=n;x=ch[x][c],i++)
		if(!ch[x][c=s[i]-'a']) ch[x][c]=++node_cnt;
	return wd[x]=1,x;
}
int fa[N],vis[N],val[N];
inline int get_fail(int rt)
{
	queue<int> q;while(!q.empty()) q.pop();
	rep(i,0,SIG-1) { int &y=ch[rt][i];if(y) q.push(y),fail[y]=rt;else y=rt; }
	while(!q.empty())
	{
		int x=q.front();q.pop();
		rep(i,0,SIG-1)
		{
			int &y=ch[x][i],f=fail[x],c=ch[f][i];
			if(y) fail[y]=c,q.push(y);else y=c;
		}
	}
	rep(i,1,node_cnt) if(fail[i]) fa[i]=fail[i],add_edge(fail[i],i);
	return 0;
}
int dfs(int x,int las=0)
{
	fa[x]=las;if(wd[x]) las=x;
	for(int i=h[x];i;i=e[i].pre) dfs(e[i].to,las);
	return 0;
}
inline int upd(int x,int t) { while(x&&vis[x]!=t) val[x]++,vis[x]=t,x=fa[x];return 0; }
inline int upd(char *s,int n,int t) { int x=rt;rep(i,1,n) x=ch[x][s[i]-'a'],upd(x,t);return 0; }
int main()
{
	int n=inn();rt=node_cnt=1;
	rep(i,1,n) scanf("%s",s+1),ps[i]=ins(s,(int)strlen(s+1));
	get_fail(rt),dfs(1),q=inn();
	rep(i,1,q)
		if(inn()==1) scanf("%s",s+1),upd(s,(int)strlen(s+1),i);
		else printf("%d\n",val[ps[inn()]]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/83346936