BZOJ 2434 [Noi2011]阿狸的打字机

题解:在线建立AC自动机,建好Fail树,a是b的子串也就是b到root的节点能沿Fail树走到a

离线所有询问,DFS一遍的时候顺便处理询问

或按b排序在AC自动机上走也可以

用树状数组维护,查询区间和即可

一开始LCA打错了竟然得了70害得我找不出错

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=200009;

int T;

int n;
int p[maxn];

int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
//	printf("%d -> %d\n",x,y);
	nex[++cntedge]=head[x];
	to[cntedge]=y;
	head[x]=cntedge;
}

int dfsclock;
int father[maxn],idx[maxn],siz[maxn];
void Dfs(int now,int fa){
	father[now]=fa;
	idx[now]=++dfsclock;
	siz[now]=1;
	for(int i=head[now];i;i=nex[i]){
		if(to[i]==fa)continue;
		Dfs(to[i],now);
		siz[now]+=siz[to[i]];
	}
}

int nn;
char s[maxn];
int ch[maxn][30];
int ff[maxn];
int dep[maxn];
int f[maxn][20];

queue<int>q;
int fai[maxn];
void GetFail(){
	fai[1]=1;
	for(int c=0;c<26;++c){
		int v=ch[1][c];
		if(v){
//			cout<<"eatingshit"<<' '<<c<<endl;
			fai[v]=1;
			Addedge(1,v);
			q.push(v);
		}
	}
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int c=0;c<26;++c){
			int v=ch[u][c];
			if(!v)continue;
			int j=fai[u];
			while((j!=1)&&(!ch[j][c]))j=fai[j];
			if(ch[j][c]){
				fai[v]=ch[j][c];
			}else{
				fai[v]=1;
			}
			Addedge(fai[v],v);
			q.push(v);
		}
	}
}

void check(int x,int dep){
	printf("%d %d\n",x,dep);
	for(int c=0;c<26;++c){
		if(ch[x][c])check(ch[x][c],dep+1);
	}
}

void LCAinit(){
	for(int i=1;i<=nn;++i)f[i][0]=ff[i];
	for(int j=1;j<=16;++j){
		for(int i=1;i<=nn;++i){
			f[i][j]=f[f[i][j-1]][j-1];
		}
	}
}
int Getlca(int u,int v){
	if(dep[u]<dep[v])swap(u,v);
	for(int j=16;j>=0;--j){
		if(dep[f[u][j]]>=dep[v]){
			u=f[u][j];
		}
	}
	if(u==v)return u;
	for(int j=16;j>=0;--j){
		if(f[u][j]!=f[v][j]){
			u=f[u][j];v=f[v][j];
		}
	}
	return f[u][0];
}

int c[maxn];
inline int lowbit(int x){
	return x&(-x);
}
void Addpoint(int x,int val){
	while(x<=nn){
		c[x]+=val;
		x+=lowbit(x);
	}
}
int Querypre(int x){
	int ret=0;
	while(x){
		ret+=c[x];
		x-=lowbit(x);
	}
	return ret;
}

int ans[maxn];
struct Querys{
	int qx,qy,t;
}que[maxn];
int cmp(const Querys &rhs1,const Querys &rhs2){
	return rhs1.qy<rhs2.qy;
}

void Minit(){
	n=cntedge=nn=dfsclock=0;
	memset(father,0,sizeof(father));
	memset(head,0,sizeof(head));
	memset(ch,0,sizeof(ch));
	memset(ff,0,sizeof(ff));
	memset(dep,0,sizeof(dep));
	memset(f,0,sizeof(f));
	memset(c,0,sizeof(c));
	while(!q.empty())q.pop();
}

int main(){
//	freopen("print.in","r",stdin);
//	freopen("print.out","w",stdout);
	Minit();
	scanf("%s",s);
	int len=strlen(s);
//	cout<<len<<endl;
	nn=1;
	int nowx=1;
	dep[nowx]=1;
	for(int i=0;i<len;++i){
		if(s[i]=='P'){
			p[++n]=nowx;
		}else if(s[i]=='B'){
			nowx=ff[nowx];
		}else{
			int c=s[i]-'a';
			if(ch[nowx][c]){
				nowx=ch[nowx][c];
			}else{
				ch[nowx][c]=++nn;
				ff[ch[nowx][c]]=nowx;
				dep[ch[nowx][c]]=dep[nowx]+1;
				nowx=ch[nowx][c];
			}
		}
	}
//	check(1,1);
	LCAinit();
	GetFail();
	Dfs(1,0);
	
	scanf("%d",&T);
	for(int i=1;i<=T;++i){
		scanf("%d%d",&que[i].qx,&que[i].qy);
		que[i].t=i;
	}
	sort(que+1,que+1+T,cmp);
//	cout<<"eatingshit"<<endl;
	for(int i=1;i<=T;++i){
		que[i].qx=p[que[i].qx];
		que[i].qy=p[que[i].qy];
//		printf("%d %d\n",que[i].qx,que[i].qy);
	}
//	cout<<"eeee"<<endl;
	int lastp=1;
	Addpoint(idx[lastp],1);
	for(int i=1;i<=T;++i){
//		cout<<i<<endl;
		int y=que[i].qy;
		int lca=Getlca(lastp,y);
//		printf("%d %d %d\n",lca,dep[lastp]-dep[lca],dep[y]-dep[lca]);
		while(lastp!=lca){
			Addpoint(idx[lastp],-1);
			lastp=ff[lastp];
		}
//		cout<<"emmmmm"<<endl;
		lastp=y;
		while(y!=lca){
//			cout<<y<<' '<<idx[y]<<endl;
			Addpoint(idx[y],1);
			y=ff[y];
		}
		ans[que[i].t]=-Querypre(idx[que[i].qx]-1)+Querypre(idx[que[i].qx]+siz[que[i].qx]-1);
	}
	for(int i=1;i<=T;++i)printf("%d\n",ans[i]);
	return 0;
}

  

posted @ 2018-02-19 21:07  ws_zzy  阅读(146)  评论(0编辑  收藏  举报