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的更多相关文章

  1. 【BZOJ 4104】 4104: [Thu Summer Camp 2015]解密运算 (智商)

    4104: [Thu Summer Camp 2015]解密运算 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 370  Solved: 237 De ...

  2. 【BZOJ】3052: [wc2013]糖果公园

    http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]} ...

  3. 【MyEclipse 2015】 逆向破解实录系列【终】(纯研究)

    声明 My Eclipse 2015 程序版权为Genuitec, L.L.C所有. My Eclipse 2015 的注册码.激活码等授权为Genuitec, L.L.C及其付费用户所有. 本文只从 ...

  4. 【MyEclipse 2015】 逆向破解实录系列【2】(纯研究)

    声明 My Eclipse 2015 程序版权为Genuitec, L.L.C所有. My Eclipse 2015 的注册码.激活码等授权为Genuitec, L.L.C及其付费用户所有. 本文只从 ...

  5. 【BZOJ】3319: 黑白树

    http://www.lydsy.com/JudgeOnline/problem.php?id=3319 题意:给一棵n节点的树(n<=1e6),m个操作(m<=1e6),每次操作有两种: ...

  6. 【BZOJ】3319: 黑白树(并查集+特殊的技巧/-树链剖分+线段树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3319 以为是模板题就复习了下hld............................. 然后n ...

  7. 【CEDEC 2015】【夏日课堂】制作事宜技术篇,新手职员挑战VR Demo开发的真相

    日文原文地址 http://www.4gamer.net/games/277/G027751/20150829002/ PS:CEDEC 2015的PPT有些要到10月才有下载,目前的都是记者照片修图 ...

  8. 【SIGGRAPH 2015】【巫师3 狂猎 The Witcher 3: Wild Hunt 】顶级的开放世界游戏的实现技术。

    [SIGGRAPH 2015][巫师3 狂猎 The Witcher 3: Wild Hunt ]顶级的开放世界游戏的实现技术 作者:西川善司 日文链接  http://www.4gamer.net/ ...

  9. 【BZOJ】【2084】【POI2010】Antisymmetry

    Manacher算法 啊……Manacher修改一下就好啦~蛮水的…… Manacher原本是找首尾相同的子串,即回文串,我们这里是要找对应位置不同的“反回文串”(反对称?233) 长度为奇数的肯定不 ...

随机推荐

  1. python学习笔记(三)之变量和字符串

    在其他语言中,变量就是有名字的存储区,可以将值存储在变量中,也即内存中.在Python中略有不同,python并不是将值存储在变量中,更像是把名字贴在值上边.所以,有些python程序员会说pytho ...

  2. elementui raido 单选框 循环渲染加:key

    <el-radio-group v-model="adminRole"> <el-radio v-for="item in adminRoles&quo ...

  3. IE浏览器Bug总结

    每每在网上搜索IE浏览器Bug时,总是骂声一片,特别是前端工程师,每天都要面对,IE浏览器特别是IE6,存在很多Bug,对Web标准的支持也拖后腿,但不可否认,IE浏览器是曾经的霸主,它的贡献也是巨大 ...

  4. ctsc&apio2018八日游

    day0: 早就知道自己是打酱油的..早就做好了打铁的准备.. Q:那你来干嘛 A:当然是来玩啊!!玩啊!啊!! emmmmm 抱着半期考不及格的卷子瑟瑟发抖地上了飞机. day1:报道!当然还有在宾 ...

  5. docker使用小记

    查看当前镜像:docker images 运行一个简单的镜像:docker run hello-world 拉取一个远程docker:docker pull centos docker中安装nginx ...

  6. LCD 每隔10分钟 自动熄灭 --打开Framebuffer console的时候【转】

    转自:http://blog.csdn.net/liujia2100/article/details/9009063 版权声明:本文为博主原创文章,未经博主允许不得转载. 之前移植LCD的时候,一切正 ...

  7. (十八)Linux开机启动管理---systemd使用

    常用命令 使某服务自动启动 systemctl enable httpd.service 使某服务不自动启动 systemctl disable httpd.service 检查服务状态 system ...

  8. 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6156 数位DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6156 题意:如题. 解法:数位DP,暴力枚举进制之后,就转化成了求L,R区间的回文数的个数,这个直接做 ...

  9. C基础 算法实现层面套路

    引言 - 从实践狗讲起 理论到实践(有了算法到实现) 中间有很多过程. 算法方面本人啥也不懂, 只能说说实现方面. 例如下面 一个普通的插入排序. // // 插入排序默认从大到小 // extern ...

  10. clearcase command (linux 常用命令)

    http://publib.boulder.ibm.com/infocenter/cchelp/v7r0m0/index.jsp?topic=/com.ibm.rational.clearcase.h ...