记录编号 |
61628 |
评测结果 |
AAAAAAAAAA |
题目名称 |
[NOI 2011]阿狸的打字机 |
最终得分 |
100 |
用户昵称 |
cstdio |
是否通过 |
通过 |
代码语言 |
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;
- }