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

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

    一个讲得很详细的题解:http://blog.csdn.net/huzecong/article/details/7769988

    思路:这题的想法有点神啊....

    先构建AC自动机,然后怎么判断一个串b是a的子串呢?用fail指针就可以了。如果a串中有节点可以通过fail指针走到b的终止节点,那么b就在a中出现过。有n个节点可以走到b,那么b就出现过n次。

    现在就有一个暴力的想法,枚举a串的每个节点的fail看是否能到b,但是这是显然会T的。

    然后我们可以倒过来想,把fail指针反向,建一棵fail树,对于b串,统计子树中有多少个a串的节点即可。

    子树的节点的dfs序是相连的。

    这样我们就可以用树状数组维护一下就好了。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int maxn=100010;
    using namespace std;
    int m,len,num,preq[maxn],nowq[maxn],sonq[maxn],l[maxn],r[maxn],bit[maxn],pos[maxn],cnt,pre[maxn],now[maxn],son[maxn],ans[maxn];char s[maxn],ch;
    void change(int x,int val){for (;x<=cnt;x+=x&-x) bit[x]+=val;}
    int query(int x){
    	int res=0;
    	for (;x;x-=x&-x) res+=bit[x];
    	return res;
    }
    void add(int a,int b){pre[++num]=now[a],now[a]=num,son[num]=b;}
    void read(int &x){
    	for (ch=getchar();!isdigit(ch);ch=getchar());
    	for (x=0;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    }
    
    struct AC_DFA{
    	int tot,ch[maxn][26],fail[maxn],q[maxn],fa[maxn],head,tail;
    	void build(){
    		int p=0,id=0;
    		for (int i=0;i<len;i++)
    			if (s[i]=='P') pos[++id]=p;
    			else if (s[i]=='B') p=fa[p];
    			else{
    				if (!ch[p][s[i]-'a']) ch[p][s[i]-'a']=++tot,fa[tot]=p;
    				p=ch[p][s[i]-'a'];
    			}
    	}
    	void getfail(){
    		head=0,q[tail=1]=0,fail[0]=-1;
    		while (head!=tail){
    			int x=q[++head];
    			for (int i=0;i<26;i++)
    				if (ch[x][i])
    					q[++tail]=ch[x][i],fail[ch[x][i]]=x==0?0:ch[fail[x]][i];
    				else ch[x][i]=x==0?0:ch[fail[x]][i];
    		}
    	}
    	void dfs(int x){
    		l[x]=++cnt;
    		for (int y=now[x];y;y=pre[y])
    			dfs(son[y]);
    		r[x]=cnt;
    	}
    	void work(){
    		int p=0,id=0;
    		change(l[0],1);
    		for (int i=0;i<len;i++)
    			if (s[i]=='P'){
    				id++;
    				for (int y=nowq[id];y;y=preq[y]){
    					int t=pos[sonq[y]];
    					ans[y]=query(r[t])-query(l[t]-1);
    				}
    			}
    			else if (s[i]=='B') change(l[p],-1),p=fa[p];
    			else p=ch[p][s[i]-'a'],change(l[p],1);
    	}
    }T;
    
    int main(){
    	scanf("%s%d",s,&m);len=strlen(s);
    	for (int i=1,x,y;i<=m;i++){
    		read(x),read(y);
    		preq[i]=nowq[y],sonq[i]=x,nowq[y]=i;
    	}
    	T.build(),T.getfail();
    	for (int i=1;i<=T.tot;i++) add(T.fail[i],i);
    	T.dfs(0),T.work();
    	for (int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    	return 0;
    }


  • 相关阅读:
    SGU 176.Flow construction (有上下界的最大流)
    POJ 2391.Ombrophobic Bovines (最大流)
    poj 1087.A Plug for UNIX (最大流)
    poj 1273.PIG (最大流)
    POJ 2112.Optimal Milking (最大流)
    SGU 196.Matrix Multiplication
    SGU 195. New Year Bonus Grant
    关于multicycle path
    ppt做gif动图
    codeforces 598A Tricky Sum
  • 原文地址:https://www.cnblogs.com/thythy/p/5493563.html
Copyright © 2011-2022 走看看