• bzoj2434: [Noi2011]阿狸的打字机


    题目链接

    bzoj2434: [Noi2011]阿狸的打字机

    题解

    建出fail树,如果fail树中只有第y个字符串那就是求x串这个点的子树和
    对于每组询问的y分类
    我们可以重新进行一次建树一样的操作,每次dfs的到字符串y
    只要在fail树上用dfs序+树状数组维护,每次把路径上的点插到bit里

    代码

    #include<queue> 
    #include<vector> 
    #include<cstdio> 
    #include<cstring> 
    #include<algorithm>  
    
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = getchar(); 
    	while(c < '0' || c > '9')c = getchar(); 
    	while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar(); 
    	return x * f; 
    } 
    
    const int maxn = 200007; 
    
    char str[maxn]; 
    int lt[maxn],n,ch[maxn][27],fail[maxn]; 
    int tot = 0; 
    int tmp[maxn][27]; 
    void buildfail() { 
    	std::queue<int>q; 
    	for(int i = 0;i < 26;++ i) if(ch[0][i])q.push(ch[0][i]); 	
    	while(!q.empty()) { 
    		int u = q.front();q.pop(); 
    		for(int i = 0;i < 26;++ i) 
    			if(ch[u][i]) { 
    				fail[ch[u][i]] = ch[fail[u]][i],q.push(ch[u][i]); 
    			} else ch[u][i] = ch[fail[u]][i]; 
    	} 	 
    } 
    
    struct Query { 
    	int x,y,id,ans; 
    	bool operator < (const Query&a) const {
    		return y < a.y; 
    	} 
    } q[maxn]; 
    int ql[maxn],qr[maxn]; 
    
    std::vector<int>v[maxn]; 
    int dfn[maxn],low[maxn]; 
    int cnt = 0; 
    void dfs(int x ) { 
    	dfn[x] = ++ cnt; 
    	for(int i = 0;i < v[x].size();++ i) dfs(v[x][i]); 
    	low[x] = cnt; 
    } 
    
    int bit[maxn]; 
    #define lowbit(x) (x & -x) 
    void add(int x,int v) { 
    	for(;x <= cnt;x += lowbit(x)) bit[x] += v; 
    } 
    int query(int x,int ret = 0) { 
    	for(;x;x -= lowbit(x)) ret += bit[x]; 
    	return ret; 
    } 
    int end[maxn]; 
    void DFS(int u) { 
    	add(dfn[u],1); 
    	if(lt[u]) 
    		for(int i = ql[lt[u]];i <= qr[lt[u]];++ i) 
    			q[i].ans = query(low[end[q[i].x]]) - query(dfn[end[q[i].x]] - 1); 
    	for(int i = 0;i < 26;++ i) 
    		if(tmp[u][i]) DFS(tmp[u][i]); 
    	add(dfn[u],-1); 
    } 
    int Ans[maxn]; 
    int pre[maxn]; 
    int main() { 
    	scanf("%s",str + 1); 
    	int now = 0; 
    	for(int i = 1;str[i];++ i) { 
    		if(str[i] >= 'a' && str[i] <= 'z') { 
    			int t = str[i] - 'a'; 
    			if(!ch[now][t]) ch[now][t] = ++ tot,pre[tot] = now; 
    			now = ch[now][t];  
    		} 
    		if(str[i] == 'B') now = pre[now]; 
    		else if(str[i] == 'P') { end[++ n] = now;lt[now] = n;}  
    	} 
    	for(int i = 0;i <= tot;++ i) for(int j = 0;j < 26;++ j) 
    		tmp[i][j] = ch[i][j]; 
    	buildfail(); 
    	for(int i = 1;i <= tot;++ i)v[fail[i]].push_back(i); 
    	dfs(0); 
    	int Q = read(); 
    	for(int i = 1;i <= Q;++ i) q[i].x = read(),q[i].y = read(),q[i].id = i; 
    	std::sort(q + 1,q + Q + 1); 
    	for(int pos = 1, i = 1; i <= Q;++ i) { 
    		ql[q[i].y] = i; 
    		while(q[pos].y == q[i].y) pos ++; 
    		qr[q[i].y] = i = pos - 1; 
    	} 
    	DFS(0); 
    	for(int i = 1;i <= Q;++ i) Ans[q[i].id] = q[i].ans; 
    	for(int i = 1;i <= Q;++ i) printf("%d
    ",Ans[i]); 
    	return 0 ; 
    } 
    
  • 相关阅读:
    如何吸引小白用户爱上你的游戏?
    产品经理应聘之感受漫谈
    罗永浩Vs王自如:浮躁的世界该如何降温?!
    从锤子手机谈产品的逼格
    博客园与51CTO博客之产品用户体验分析
    web网站 Vs 移动App 谁更能打动你?之 产品经理篇
    不要只甘于做一个程序员
    我的程序员工作经历(二) 之 谈合作
    OpenCV 之 神经网络 (一)
    Qt 之 QtConcurrent
  • 原文地址:https://www.cnblogs.com/sssy/p/9520651.html
Copyright © 2020-2023  润新知