zoukankan      html  css  js  c++  java
  • BZOJ 2434: [Noi2011]阿狸的打字机

    2434: [Noi2011]阿狸的打字机

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 2776  Solved: 1547
    [Submit][Status][Discuss]

    Description

     阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。

    经阿狸研究发现,这个打字机是这样工作的:

    l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。

    l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。

    l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。

    例如,阿狸输入aPaPBbP,纸上被打印的字符如下:

    a

    aa

    ab

    我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。

    阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?

    Input

     输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。

    第二行包含一个整数m,表示询问个数。

    接下来m行描述所有由小键盘输入的询问。其中第i行包含两个整数x, y,表示第i个询问为(x, y)。

    Output

     输出m行,其中第i行包含一个整数,表示第i个询问的答案。

    Sample Input

    aPaPBbP

    3

    1 2

    1 3

    2 3

    Sample Output

    2

    1

    0

    HINT

     1<=N<=10^5


    1<=M<=10^5

    输入总长<=10^5

    Source

    Trie

    分析:

    很显然的一点就是我们把fail树拎出来,然后y串在x的子树中的出现节点数就是x在y中的出现次数...

    但是显然我们不能直接在线修改查询,问题就在于修改次数过多...

    所以可以考虑离线,处理出fail树的dfs序,用树状数组维护区间和,把第i个串的节点处设为1,然后查询子树区间和...

    由于这道题的输入的特殊性,所以做到$O(nlgn)$...

    我还是太弱了...只能想到fail树...不能想到dfs序维护区间和...

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    //by NeighThorn
    using namespace std;
    
    const int maxn=100000+5;
    
    int n,cnt,dfn,tot,head,tail,q[maxn],fa[maxn],be[maxn],en[maxn],hd[maxn],to[maxn],ans[maxn],nxt[maxn],node[maxn],tree[maxn];
    
    char s[maxn];
    
    struct trie{
    	int fail,nxt[26];
    }tr[maxn];
    
    struct M{
    	int x,y,id;
    	friend bool operator < (M a,M b){
    		return a.y<b.y;
    	}
    }query[maxn];
    
    inline void add(int x,int y){
    	to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
    }
    
    inline void build(void){
    	int p=0;tr[0].fail=-1;
    	for(int i=0;s[i];i++){
    		if(s[i]=='B')
    			p=fa[p];
    		else if(s[i]=='P')
    			node[++cnt]=p;
    		else{
    			if(!tr[p].nxt[s[i]-'a'])
    				tr[p].nxt[s[i]-'a']=++tot,tr[tot].fail=-1;
    			fa[tr[p].nxt[s[i]-'a']]=p;
    			p=tr[p].nxt[s[i]-'a'];
    		}
    	}
    }
    
    inline void buildACM(void){
    	head=0,tail=0,q[0]=0;
    	while(head<=tail){
    		int id=q[head++],p=-1;
    		for(int i=0;i<26;i++)
    			if(tr[id].nxt[i]){
    				if(id){
    					p=tr[id].fail;
    					while(p!=-1){
    						if(tr[p].nxt[i]){
    							tr[tr[id].nxt[i]].fail=tr[p].nxt[i];
    							break;
    						}
    						p=tr[p].fail;
    					}
    					if(p==-1) tr[tr[id].nxt[i]].fail=0;
    				}
    				else
    					tr[tr[id].nxt[i]].fail=0;
    				q[++tail]=tr[id].nxt[i];
    			}
    	}
    }
    
    inline void dfs(int root){
    	be[root]=++dfn;
    	for(int i=hd[root];i!=-1;i=nxt[i])
    		dfs(to[i]);
    	en[root]=dfn;
    }
    
    inline void insert(int x,int y){
    	for(;x<=dfn;x+=x&-x)
    		tree[x]+=y;
    }
    
    inline int Query(int x){
    	int res=0;
    	for(;x;x-=x&-x)
    		res+=tree[x];
    	return res;
    }
    
    inline void solve(void){
    	int p=0,j=1,lala=0;
    	for(int i=0;s[i];i++){
    		if(s[i]=='B')
    			insert(be[p],-1),p=fa[p];
    		else if(s[i]=='P'){
    			lala++;
    			while(query[j].y==lala)
    				ans[query[j].id]=Query(en[node[query[j].x]])-Query(be[node[query[j].x]]-1),j++;
    		}
    		else
    			p=tr[p].nxt[s[i]-'a'],insert(be[p],1);
    	}
    }
    
    signed main(void){
    	memset(hd,-1,sizeof(hd));
    	scanf("%s%d",s,&n);dfn=tot=cnt=0;
    	build();buildACM();cnt=0;
    	for(int i=1;i<=tot;i++)
    		add(tr[i].fail,i);
    	dfs(0);
    	for(int i=1;i<=n;i++)
    		scanf("%d%d",&query[i].x,&query[i].y),query[i].id=i;
    	sort(query+1,query+n+1);solve();
    	for(int i=1;i<=n;i++)
    		printf("%d
    ",ans[i]);
    	return 0;
    }
    

      


    By NeighThorn

  • 相关阅读:
    poj 3280 Cheapest Palindrome(区间DP)
    POJ 2392 Space Elevator(多重背包)
    HDU 1285 定比赛名次(拓扑排序)
    HDU 2680 Choose the best route(最短路)
    hdu 2899 Strange fuction (三分)
    HDU 4540 威威猫系列故事――打地鼠(DP)
    HDU 3485 Count 101(递推)
    POJ 1315 Don't Get Rooked(dfs)
    脱离eclipse,手动写一个servlet
    解析xml,几种方式
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6406342.html
Copyright © 2011-2022 走看看