zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",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
    ",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
    ",ans[i]);
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    GL追溯
    Oracle XML Publisher中需要实现每页打印固定行数
    Form开发过程中积累下来的技巧:
    查询EBS 系统在线人数
    Oracle EBS 二次开发 FND_GLOBAL PACKAGE 返回全局变量
    Oracle EBS PA模块费用分摊与转资摘记
    PA模块常用表
    Oracle Form删除list项
    获取EBS用户密码
    JavaScript中const,var,let区别与用法
  • 原文地址:https://www.cnblogs.com/zzyer/p/8454431.html
Copyright © 2011-2022 走看看