记录编号 61628 评测结果 AAAAAAAAAA
题目名称 [NOI 2011]阿狸的打字机 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.498 s
提交时间 2013-06-13 14:10:28 内存使用 36.36 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
const int SIZEN=200000,INF=0x7fffffff;
class TTREE{//字典树
public:
	char pos;
	int father;
	bool lea;//是否叶子
	int next[30];//next[i]存的是下一位'A'+i
	TTREE(){
		pos=father=lea=0;
		for(int i=0;i<30;i++) next[i]=0;
	}
};
TTREE tt[SIZEN];
TTREE& root=tt[0];
int tot=0;
int M,N;
string str;//输入的字串
int pri[SIZEN]={0};//pri[i]表示第i个打印的字串对应的节点
int nump=0;
int fail[SIZEN]={0};//真・fail指针
class FTREE{
public:
	int father;
	vector<int> son;//子节点
};
FTREE ft[SIZEN];
int dfn[SIZEN]={0};
int low[SIZEN]={0},high[SIZEN]={0};
bool visit[SIZEN]={0};
int timer=1;
void DFS(int x){
	if(visit[x]) return;
	visit[x]=true;
	dfn[x]=timer;
	low[x]=high[x]=timer;
	timer++;
	int i;
	for(i=0;i<ft[x].son.size();i++) DFS(ft[x].son[i]);
	low[ft[x].father]=min(low[ft[x].father],low[x]);
	high[ft[x].father]=max(high[ft[x].father],high[x]);
}
void addedge(int x,int y){//x指向y,x是父节点
	ft[x].son.push_back(y);
	ft[y].father=x;
}
void singlefail(int x){
	int ch=tt[x].pos-'a';
	int temp=fail[tt[x].father];
	while(temp!=0&&tt[temp].next[ch]==0){
		temp=fail[temp];
	}
	fail[x]=tt[temp].next[ch];
	addedge(tt[temp].next[ch],x);
}
void getfail(void){
	queue<int> Q;
	int i;
	fail[0]=0;
	for(i=0;i<26;i++){
		if(root.next[i]){
			Q.push(root.next[i]);
			fail[root.next[i]]=0;
			addedge(0,root.next[i]);
		}
	}
	int x;
	while(!Q.empty()){
		x=Q.front();Q.pop();
		for(i=0;i<26;i++){
			if(tt[x].next[i]!=0){
				singlefail(tt[x].next[i]);
				Q.push(tt[x].next[i]);
			}
		}
	}
}
void addson(int x,char ch){
	if(tt[x].next[ch-'a']) return;
	tt[x].next[ch-'a']=++tot;
	tt[tot].pos=ch;
	tt[tot].father=x;
}
void maketree(void){
	int i,temp;
	temp=0;//当前访问的节点
	for(i=0;i<str.size();i++){
		if(str[i]=='B') temp=tt[temp].father;
		else if(str[i]=='P') pri[++nump]=temp;
		else{
			addson(temp,str[i]);
			temp=tt[temp].next[str[i]-'a'];
		}
	}
	N=tot+1;
	for(i=0;i<=N;i++) low[i]=INF;
}
class REQ{
public:
	int pos;
	int x,y;
};
REQ r[SIZEN];
bool operator < (REQ a,REQ b){
	return a.y<b.y;
}
void read(void){
	cin>>str;
	cin>>M;
	int i;
	for(i=1;i<=M;i++){
		scanf("%d%d",&r[i].x,&r[i].y);
		r[i].pos=i;
	}
	sort(r+1,r+1+M);
}
int sum[SIZEN]={0};//真・树状数组
int lowbit(int x){
	return x&(-x);
}
void change(int x,int num){
	while(x<=N){
		sum[x]+=num;
		x+=lowbit(x);
	}
}
int getsum(int x){
	int ans=0;
	while(x>0){
		ans+=sum[x];
		x-=lowbit(x);
	}
	return ans;
}
int ans[SIZEN]={0};
void ask(void){
	int i,j=1,temp,nowp;
	temp=0;
	int nowr=r[1].y;
	nowp=0;
	char ch;
	for(i=0;i<str.size();i++){
		if(str[i]=='B'){
			change(dfn[temp],-1);
			temp=tt[temp].father;
		}
		else if(str[i]=='P'){
			nowp++;
			if(nowp==nowr){
				while(j<=M&&r[j].y==nowr){
					ans[r[j].pos]=getsum(high[pri[r[j].x]])-getsum(low[pri[r[j].x]]-1);
					j++;
				}
				if(j>M) break;
				nowr=r[j].y;
			}
		}
		else{
			ch=str[i];
			ch-='a';
			temp=tt[temp].next[(int)ch];
			change(dfn[temp],1);
		}
	}
	for(i=1;i<=M;i++) printf("%d\n",ans[i]);
}
int main(){
	freopen("noi2011_type.in","r",stdin);
	freopen("noi2011_type.out","w",stdout);
	read();
	maketree();
	getfail();
	DFS(0);
	ask();
	return 0;
}