【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) 长度为奇数的肯定不 ...
随机推荐
- [uva11991]map和vector的入门
给你一个长度为n的数组,进行m次询问,每次询问输入k和v,输出第k次出现v时的下标是多少. n<=1e6 用vector动态开空间,map使数值结合.map每次查找效率大约为logn. map的 ...
- ios资源加载策略
做了好几个月的ios,大框架都是别人搭好的,自己只是实现逻辑,很是失落.慢慢开始整理学习一些概念类的东西吧,希望自己能提高点. cocos2d-x从cocos2d-2.0-x-2.0.2开始,考虑到自 ...
- Farey Sequence (欧拉函数+前缀和)
题目链接:http://poj.org/problem?id=2478 Description The Farey Sequence Fn for any integer n with n >= ...
- Linux-进程间通信(四): 域套接字
1. 域套接字: (1) 只能用于同一设备上不同进程之间的通信: (2) 效率高于网络套接字.域套接字仅仅是复制数据,并不走协议栈: (3) 可靠,全双工: 2. 域套接字地址结构: struct s ...
- qt-creator
https://github.com/qt-creator/qt-creator https://github.com/qt-creator
- linux和ubuntu防火墙相关命令
1.永久有效 开启: chkconfig iptables on 关闭: chkconfig iptables off 2.即刻生效 开启: service iptables start 关闭: se ...
- 查看linux 下进程运行时间(转)
原文地址:http://blog.csdn.net/tspangle/article/details/11731317 可通过ps 来查看,通过参数 -o 来查看 如: ps -eo pid,tty, ...
- iframe的一些介绍
iframe 元素会创建包含另外一个文档的内联框架(即行内框架) 提示:您可以把需要的文本放置在 <iframe> 和 </iframe> 之间,这样就可以应对无法理解 ifr ...
- 微软推出ASP.NET Core 2.0,并支持更新Visual Studio 2017
微软推出ASP.NET Core 2.0的一般可用性,并发布.NET Core 2.0.该公司还推出了其旗舰集成开发环境(IDE)的更新:Visual Studio 2017版本15.3和Visual ...
- django “如何”系列6:如何部署django
django满满的快捷方法是的web开发者活的更轻松,但是,如果你不能部署你的站点的话,这是一点用都没有的.不违初衷,部署的简化也是django的一大目标.你可以有几个方法轻松的部署django 由于 ...