• [NOI2011] 阿狸的打字机


    \(\text{Solution}\)

    对于一组 \(x,y\)
    考虑 \(AC\) 自动机暴力运作的过程
    就是在 \(Trie\) 上沿着 \(y\) 的路径走,每走到一处就暴力跳 \(fail\)
    碰到一个 \(x\) 就产生 \(1\) 的贡献
    \(y\) 到根的路径上的点,有多少个能一直跳 \(fail\) 碰到 \(x\)
    \(fail\) 建成一棵树
    那么碰到 \(x\) 就变成了 \(x\) 的子树中有这个点
    这样不难想到离线,\(\text{dfs Trie}\) 树,把根到当前点的路径在 \(fail\) 树上打标记
    询问就是问 \(fail\) 树中 \(x\) 的子树内有多少个点被打了标记
    树状数组即可
    (没想到一遍就过了

    \(\text{Code}\)

    #include <cstdio>
    #include <cstring>
    #define IN inline
    using namespace std;
    
    const int N = 1e5 + 5;
    int n, ans[N], id[N], cnt, size;
    char s[N];
    
    int h[N], tot, hq[N], totq;
    struct edge{int to, nxt, id;}e[N], Q[N];
    IN void add(int x, int y) {e[++tot] = edge{y, h[x]}, h[x] = tot;}
    IN void add(int x, int y, int id) {Q[++totq] = edge{y, hq[x], id}, hq[x] = totq;}
    
    int dfn[N], dfc, siz[N];
    void dfs_fail(int x) {
    	dfn[x] = ++dfc, siz[x] = 1;
    	for(int i = h[x], v; i; i = e[i].nxt) dfs_fail(v = e[i].to), siz[x] += siz[v];
    }
    
    struct BIT {
    	int c[N];
    	IN int lowbit(int x) {return x & -x;}
    	IN void add(int x, int v) {for(; x <= dfc; x += lowbit(x)) c[x] += v;}
    	IN int query(int x) {int s = 0; for(; x; x -= lowbit(x)) s += c[x]; return s;}
    }T;
    
    struct ACAM {
    	int tr[N][26], fail[N], q[N], fa[N], now, nxt[N][26];
    	IN ACAM() {now = 0;}
    	
    	IN void insert(char ch) {
    		int c = ch - 'a';
    		if (!tr[now][c]) tr[now][c] = ++size;
    		fa[tr[now][c]] = now, now = tr[now][c];
    	}
    	IN void build() {
    		for(int i = 0; i <= size; i++)
    			for(int j = 0; j < 26; j++) nxt[i][j] = tr[i][j];
    		
    		int h = 0, t = 0, x;
    		for(int i = 0; i < 26; i++) if (tr[0][i]) q[++t] = tr[0][i];
    		while (h < t) {
    			x = q[++h];
    			for(int i = 0; i < 26; i++)
    				if (tr[x][i]) fail[tr[x][i]] = tr[fail[x]][i], q[++t] = tr[x][i];
    				else tr[x][i] = tr[fail[x]][i];
    		}
    		for(int i = 1; i <= size; i++) add(fail[i], i);
    	}
    	
    	void dfs(int x) {
    		T.add(dfn[x], 1);
    		for(int i = hq[x], v; i; i = Q[i].nxt)
    			ans[Q[i].id] = T.query(dfn[v = Q[i].to] + siz[v] - 1) - T.query(dfn[v] - 1);
    		for(int i = 0; i < 26; i++)
    			if (nxt[x][i]) dfs(nxt[x][i]);
    		T.add(dfn[x], -1);
    	}
    }AC;
    
    int main() {
    	scanf("%s", s); int len = strlen(s), st = len;
    	for(int i = 0; i < len; i++)
    		if (s[i] != 'B' && s[i] != 'P') {st = i; break;}
    	if (st < len) AC.insert(s[st]);
    	for(int i = st + 1; i < len; i++)
    		if (s[i] == 'P') id[++cnt] = AC.now;
    		else if (s[i] == 'B') AC.now = AC.fa[AC.now];
    		else AC.insert(s[i]);
    	AC.build(), scanf("%d", &n);
    	for(int i = 1, x, y; i <= n; i++) scanf("%d%d", &x, &y), add(id[y], id[x], i);
    	dfs_fail(0), AC.dfs(0);
    	for(int i = 1; i <= n; i++) printf("%d\n", ans[i]);
    }
    
  • 相关阅读:
    SQL易错总结1
    线程池使用总结
    多线程的上下文切换
    SQL 排序按指定内容优先排序
    System x 服务器制作ServerGuide U盘安装Windows Server 2008 操作系统 --不格式化盘
    错误“该伙伴事务管理器已经禁止了它对远程/网络事务的支持”解决方案
    sql server 2012 链接服务器不能链接sql server 2000的解决方案 ,
    sqlserver2005版本的mdf文件,还没有log文件,
    BCP SQL导出EXCEL常见问题及解决方法;数据导出存储过程
    Nginx
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/16473174.html
Copyright © 2020-2023  润新知