【BZOJ】【P2434】【Noi2011】【阿狸的打字机】【题解】【fail树+dfs序+树状数组】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2434

题解很多我就不讲了

Code:

#include<bits/stdc++.h>
#define idx(c) (c-'a')
#define lowbit(x) (x&-x)
using namespace std;
const int maxn=1e5+5;
typedef pair<int,int> pi;
vector<int>d,lef,rig;
vector<pi>Q[maxn];
char s[maxn];
int n,m,len,anss[maxn],tot,mp[maxn],vmp[maxn];
struct node{
	int val,id;
	node *go[26],*fail,*last,*pre;
	vector<node*>son;
	node(node *C=0){
		for(int i=0;i<26;i++)go[i]=C;
		fail=last=C;pre=C;id=0;val=0;
	}
}*Null,*root;
int cnt=0;
node *newnode(){
	node *x=new node(Null);
	x->id=++cnt;return x;
}
void build(){
	Null=newnode();Null->fail=Null->last=Null;
	for(int i=0;i<26;i++)Null->go[i]=Null;
	root=Null;
	node *u=root;
	for(int i=0;i<len;i++){
		if(s[i]=='B'){u=u->pre;continue;}
		if(s[i]=='P'){++n;mp[n]=u->val?mp[u->val]:n;u->val=u->val?u->val:n;vmp[u->val]=u->id;continue;}
		int v=idx(s[i]);
		if(u->go[v]==Null)u->go[v]=newnode();
		u->go[v]->pre=u;u=u->go[v];
	}	
}
void get_fail(){
	queue<node*>q;
	for(int i=0;i<26;i++)if(root->go[i]!=Null)
	q.push(root->go[i]),root->son.push_back(root->go[i]);
	while(!q.empty()){
		node *u=q.front(),*v;q.pop();
		for(int i=0;i<26;i++)if((v=u->go[i])!=Null){
			q.push(v);node *j=u->fail;
			while(j!=Null&&j->go[i]==Null)j=j->fail;
			v->fail=j->go[i];j->go[i]->son.push_back(v);
			v->last=v->fail->val?v->fail:v->last;
		}
	}
}
int get(int x){
	int ans=0;
	while(x)ans+=d[x],x-=lowbit(x);
	return ans;
}
void updata(int x,int f){
	while(x<d.size())d[x]+=f,x+=lowbit(x);
}
void _dfs(node *u){
	lef[u->id]=++tot;
	for(int i=0;i<u->son.size();i++)
		_dfs(u->son[i]);
	rig[u->id]=tot;	
}
void dfs(node *u){
	updata(lef[u->id],1);
	for(int i=0;i<Q[u->val].size();i++)
	anss[Q[u->val][i].second]=get(rig[vmp[Q[u->val][i].first]])-get(lef[vmp[Q[u->val][i].first]]-1);
	for(int i=0;i<26;i++)if(u->go[i]!=Null)
	dfs(u->go[i]);
	updata(lef[u->id],-1);
}
int main(){
	scanf("%s",s);len=strlen(s);
	build();get_fail();
	d.resize(cnt+1);
	lef.resize(cnt+1);
	rig.resize(cnt+1);
	_dfs(root);
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int x,y;scanf("%d%d",&x,&y);
		Q[mp[y]].push_back(make_pair(mp[x],i));
	}dfs(root);
	for(int i=1;i<=m;i++)printf("%d\n",anss[i]);
	return 0;
}


你可能感兴趣的:(bzoj)