【BZOJ 3881】【COCI 2015】Divljak
http://www.lydsy.com/JudgeOnline/problem.php?id=3881
好难的一道题啊qwq
一开始我想对T建AC自动机,根本不可做。
正解是对S建AC自动机。
fail树的性质:一棵子树中所有的点都有子树的根这个后缀。
对于要插入的一个串\(P_x\),我们在AC自动机上匹配它。
考虑问题要问\(S_x\)是多少\(P_x\)的子串,子串可以表示成一个前缀的后缀。
匹配过程中经过的所有点都可以当做\(P_x\)的一个前缀,暴力做法是对每个当做\(P_x\)前缀的点暴力沿着fail指针往上跳,对经过的所有点染上一种颜色。
回答询问就是回答代表\(S_x\)的结点有多少不同的颜色。
对于上面那个暴力做法,可以在每个代表\(P_x\)前缀的结点上打上颜色,回答询问直接统计子树里有多少种不同的颜色即可。
可以用bits维护dfs序,但在一棵子树里同一种颜色可能有两个,对这棵子树的dfs序贡献必须是1。
有一个非常神奇的东西,把当前所有要打上颜色的结点按dfs序排序,每个节点上+1,排序后相邻结点的lca出-1。
这样对于一棵子树里的所有颜色相同的结点,它们总的贡献是1。
好神啊,不过\(2*10^6\)能用\(O(n\log n)\)?
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2000003;
struct node {int nxt, to;} E[N];
int id[N], qu[N], ch[N][26], cnt = 0, cnt2 = 1, fail[N], point[N];
void ins(int u, int v) {E[++cnt] = (node) {point[u], v}; point[u] = cnt;}
void insert(int num, char *s) {
int x, tmp = 1, len = strlen(s);
for (int i = 0; i < len; ++i) {
x = s[i] - 'a';
if (ch[tmp][x] != 0) tmp = ch[tmp][x];
else tmp = ch[tmp][x] = ++cnt2;
}
id[num] = tmp;
}
void BFS() {
int p = 0, q = 1, f, x, v; qu[1] = 1;
while (p != q) {
x = qu[++p];
for (int i = 0; i < 26; ++i)
if (ch[x][i]) {
v = qu[++q] = ch[x][i];
f = fail[x];
while (f && ch[f][i] == 0)
f = fail[f];
fail[v] = f ? ch[f][i] : 1;
ins(fail[v], v);
}
}
}
int tot = 0, n, deep[N], L[N], R[N], sz[N], top[N], son[N], fa[N];
char s[N];
void dfs(int x) {
L[x] = ++tot; sz[x] = 1;
for (int i = point[x], v = E[i].to; i; v = E[i = E[i].nxt].to) {
fa[v] = x; deep[v] = deep[x] + 1;
dfs(v); sz[x] += sz[v];
if (son[x] == 0 || sz[v] > sz[son[x]])
son[x] = v;
}
R[x] = tot;
}
void dfs2(int x) {
if (son[x]) {
top[son[x]] = top[x];
dfs2(son[x]);
}
for (int i = point[x], v = E[i].to; i; v = E[i = E[i].nxt].to)
if (v != son[x])
top[v] = v, dfs2(v);
}
int LCA(int x, int y) {
while (top[x] != top[y]) {
if (deep[top[x]] < deep[top[y]])
swap(x, y);
x = fa[top[x]];
}
return deep[x] < deep[y] ? x : y;
}
bool cmp(int x, int y) {return L[x] < L[y];}
int bits[N], a[N];
void update(int x, int d) {
for (; x <= tot; x += (x & (-x)))
bits[x] += d;
}
int sum(int x) {
int ret = 0;
for (; x; x -= (x & (-x)))
ret += bits[x];
return ret;
}
void add(char *s) {
int len = strlen(s), x, tmp = 1, tt = 0;
for (int i = 0; i < len; ++i) {
x = s[i] - 'a';
if (ch[tmp][x]) tmp = ch[tmp][x];
else {
while (tmp && ch[tmp][x] == 0) tmp = fail[tmp];
if (ch[tmp][x]) tmp = ch[tmp][x];
else tmp = 1;
}
a[++tt] = tmp;
update(L[tmp], 1);
}
stable_sort(a + 1, a + tt + 1, cmp);
for (int i = 2; i <= tt; ++i)
update(L[LCA(a[i - 1], a[i])], -1);
}
int Sum(int x) {
return sum(R[x]) - sum(L[x] - 1);
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%s", s);
insert(i, s);
}
BFS();
dfs(1);
top[1] = 1; dfs2(1);
int q, op;
scanf("%d", &q);
while (q--) {
scanf("%d", &op);
if (op == 1) {
scanf("%s", s);
add(s);
} else {
scanf("%d", &op);
printf("%d\n", Sum(id[op]));
}
}
return 0;
}
【BZOJ 3881】【COCI 2015】Divljak的更多相关文章
- 【BZOJ 4104】 4104: [Thu Summer Camp 2015]解密运算 (智商)
4104: [Thu Summer Camp 2015]解密运算 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 370 Solved: 237 De ...
- 【BZOJ】3052: [wc2013]糖果公园
http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]} ...
- 【MyEclipse 2015】 逆向破解实录系列【终】(纯研究)
声明 My Eclipse 2015 程序版权为Genuitec, L.L.C所有. My Eclipse 2015 的注册码.激活码等授权为Genuitec, L.L.C及其付费用户所有. 本文只从 ...
- 【MyEclipse 2015】 逆向破解实录系列【2】(纯研究)
声明 My Eclipse 2015 程序版权为Genuitec, L.L.C所有. My Eclipse 2015 的注册码.激活码等授权为Genuitec, L.L.C及其付费用户所有. 本文只从 ...
- 【BZOJ】3319: 黑白树
http://www.lydsy.com/JudgeOnline/problem.php?id=3319 题意:给一棵n节点的树(n<=1e6),m个操作(m<=1e6),每次操作有两种: ...
- 【BZOJ】3319: 黑白树(并查集+特殊的技巧/-树链剖分+线段树)
http://www.lydsy.com/JudgeOnline/problem.php?id=3319 以为是模板题就复习了下hld............................. 然后n ...
- 【CEDEC 2015】【夏日课堂】制作事宜技术篇,新手职员挑战VR Demo开发的真相
日文原文地址 http://www.4gamer.net/games/277/G027751/20150829002/ PS:CEDEC 2015的PPT有些要到10月才有下载,目前的都是记者照片修图 ...
- 【SIGGRAPH 2015】【巫师3 狂猎 The Witcher 3: Wild Hunt 】顶级的开放世界游戏的实现技术。
[SIGGRAPH 2015][巫师3 狂猎 The Witcher 3: Wild Hunt ]顶级的开放世界游戏的实现技术 作者:西川善司 日文链接 http://www.4gamer.net/ ...
- 【BZOJ】【2084】【POI2010】Antisymmetry
Manacher算法 啊……Manacher修改一下就好啦~蛮水的…… Manacher原本是找首尾相同的子串,即回文串,我们这里是要找对应位置不同的“反回文串”(反对称?233) 长度为奇数的肯定不 ...
随机推荐
- [uva11174]村民排队 递推+组合数+线性求逆元
n(n<=40000)个村民排成一列,每个人不能排在自己父亲的前面,有些人的父亲不一定在.问有多少种方案. 父子关系组成一个森林,加一个虚拟根rt,转化成一棵树. 假设f[i]表示以i为根的子树 ...
- oracle scott用户不存在
scott用户拥有一些基础的数据表,可以供我们练习sql.先执行 alter user scott account unlock; 查看scott用户是否存在 当scott用户不存在,我们就需要在$O ...
- js_一个简单的30分钟循环倒计时
吐槽段: 需求的变更是千变万化的,至少在你说服和你打交道的那位谁谁谁之前. 创业公司就是这样,产品经理一个想法,就是改改改,管你改起来复杂不复杂,在他们眼里都是非常简单的. 今天的一个小改动需求,把活 ...
- 64_g5
golang-github-kr-text-devel-0-0.11.git6807e77.f..> 11-Feb-2017 07:48 14250 golang-github-kr-text- ...
- [c++,bson] linux 使用 BSON 编程[www]
[c++,bson] linux 使用 BSON 编程 http://blog.chinaunix.net/uid-28595538-id-4987410.html 1.js db=db.getSib ...
- Oracle sql中的正则表达式
SELECT first_name, last_nameFROM employeesWHERE REGEXP_LIKE (first_name, '^Ste(v|ph)en$'); FIRST_NAM ...
- FineReport——表单设计
在单元格的数据设置这一选项中,有分组,列表,汇总三个选项.分组显示,即将相同的项合并,列表则将每一行的数据逐一的展示,不会合并相同的值,每一行的是完整的一条记录,而汇总则是将数字型数据进行汇总. 分组 ...
- 虚拟机 VMware Workstation12 安装Ubuntu系统
Ubuntu 系统是一款优秀的.基于GNU/Linux 的平台的桌面系统. 当然,目前为止很多应用程序还完全不能允许运行在 Ubuntu 系统上,而且 Ubuntu 的界面.使用方法会让大部分Wind ...
- LeetCode解题报告—— Unique Binary Search Trees & Binary Tree Level Order Traversal & Binary Tree Zigzag Level Order Traversal
1. Unique Binary Search Trees Given n, how many structurally unique BST's (binary search trees) that ...
- 光流optical flow基本原理与实现
光流(optical flow)是什么呢?名字很专业,感觉很陌生,但本质上,我们是最熟悉不过的了.因为这种视觉现象我们每天都在经历.从本质上说,光流就是你在这个运动着的世界里感觉到的明显的视觉运动(呵 ...