3881: [Coci2015]Divljak

题意:添加新文本串,询问某个模式串在多少种文本串里出现过


模式串建AC自动机,考虑添加一个文本串,走到的节点记录下来求树链的并

方法是按dfs序排序去重,每个点+1,相邻点lca-1

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=4e6+5;
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
} int n, Q, op, x;
char s[N];
struct edge {int v, ne;} e[N];
int cnt=1, h[N];
inline void ins(int u, int v) {//printf("ins %d %d\n",u,v);
e[++cnt]=(edge){v, h[u]}; h[u]=cnt;} namespace ac{
struct meow{int ch[26], fail, val;} t[N];
int pos[N], sz;
void insert(char *s, int id) {
int len = strlen(s+1), u=0;
for(int i=1; i<=len; i++) {
int c=s[i]-'a';
if(!t[u].ch[c]) t[u].ch[c] = ++sz;
u=t[u].ch[c];
}
pos[id]=u;
}
int q[N], head, tail;
void build() {
head=tail=1;
for(int i=0; i<26; i++) if(t[0].ch[i]) q[tail++] = t[0].ch[i];
while(head != tail) {
int u=q[head++];
for(int i=0; i<26; i++) {
int &v = t[u].ch[i];
if(!v) v = t[t[u].fail].ch[i];
else t[v].fail = t[t[u].fail].ch[i], q[tail++]=v;
}
}
for(int i=1; i<=sz; i++) ins(t[i].fail+1, i+1);
}
}using ac::t; using ac::sz; int L[N], R[N], dfc, mx[N], deep[N], size[N], fa[N], top[N];
void dfs(int u) {
size[u]=1;
for(int i=h[u];i;i=e[i].ne) {
int v=e[i].v;
fa[v]=u; deep[v]=deep[u]+1;
dfs(v);
size[u]+=size[v];
if(size[v] > size[mx[u]]) mx[u]=v;
}
}
void dfs(int u, int anc) {
L[u] = ++dfc;
top[u] = anc;
if(mx[u]) dfs(mx[u], anc);
for(int i=h[u];i;i=e[i].ne) if(e[i].v != mx[u]) dfs(e[i].v, e[i].v);
R[u] = dfc;
}
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;
} int c[N];
inline void add(int p, int d) { //printf("add %d %d\n",p,d);
if(p==0) puts("nooo");
for(; p<=sz+1; p+=p&-p) c[p]+=d;}
inline int sum(int p) { //printf("sum %d\n",p);
if(p==-1) puts("nooo");
int ans=0; for(; p; p-=p&-p) ans+=c[p]; return ans;} int a[N];
inline bool cmp(int x, int y) {return L[x]<L[y];}
void solve(char *s) { //printf("solve %s\n",s+1);
int len=strlen(s+1), u=0, p=0;
for(int i=1; i<=len; i++) {
u=t[u].ch[s[i]-'a'];
a[++p]=u+1;
}
sort(a+1, a+1+p, cmp); p = unique(a+1, a+1+p) - a - 1;
for(int i=1; i<=p; i++) {
add(L[a[i]], 1);
if(i!=1) add(L[ lca(a[i], a[i-1]) ], -1);
}
}
int que(int x) { //printf("que %d\n",x);
return sum(R[x]) - sum(L[x]-1);
}
int main() {
freopen("in","r",stdin);
n=read();
for(int i=1; i<=n; i++) scanf("%s",s+1), ac::insert(s, i);
ac::build();
dfs(1); dfs(1, 1); //puts("hi");
//for(int i=1; i<=sz+1; i++) printf("LR %d %d %d\n", i, L[i], R[i]);
Q=read();
for(int i=1; i<=Q; i++) {
op=read();
if(op==1) scanf("%s",s+1), solve(s);
else printf("%d\n", que(ac::pos[read()]+1));
}
}

BZOJ 3881: [Coci2015]Divljak [AC自动机 树链的并]的更多相关文章

  1. 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组

    题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

  2. bzoj 3881: [Coci2015]Divljak AC自动机

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3881 题解: 这道题我想出了三种做法,不过只有最后一种能过. 第一种: 首先我们把所有的 ...

  3. BZOJ 3881[COCI2015]Divljak (AC自动机+dfs序+lca+BIT)

    显然是用AC自动机 先构建好AC自动机,当B中插入新的串时就在trie上跑,对于当前点,首先这个点所代表的串一定出现过,然后这个点指向的fail也一定出现过.那么我们把每个点fail当作父亲,建一棵f ...

  4. BZOJ3881[Coci2015]Divljak——AC自动机+树状数组+LCA+dfs序+树链的并

    题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

  5. BZOJ 3881: [Coci2015]Divljak

    3881: [Coci2015]Divljak Time Limit: 20 Sec  Memory Limit: 768 MBSubmit: 553  Solved: 176[Submit][Sta ...

  6. BZOJ 3881 [Coci2015]Divljak(AC自动机+树状数组)

    建立AC自动机然后,加入一个串之后考虑这个串的贡献.我们把这个串扔到AC自动机里面跑.最后对经过每一个点到的这个点在fail树的根的路径上的点有1的贡献.求链的并,我们把这些点按DFS序排序,然后把每 ...

  7. BZOJ 3881 [COCI2015]Divljak (Trie图+Fail树+树链的并+树状数组维护dfs序)

    题目大意: Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

  8. bzoj 3881 [Coci2015]Divljak fail树+树链的并

    题目大意 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: "1 P",Bob往自己的集合里添 ...

  9. 2019牛客多校八 H. How Many Schemes (AC自动机,树链剖分)

    大意: 给定树, 每条边有一个字符集合, 给定$m$个模式串, $q$个询问$(u,v)$, 对于路径$(u,v)$中的所有边, 每条边从对应字符集合中取一个字符, 得到一个串$s$, 求$s$至少包 ...

随机推荐

  1. 2017年 JavaScript 框架回顾 -- React生态系统

    前一篇文章中,我们介绍了2017年 JavaScript 框架的整体情况.我们也了解到在众多的前端框架中,目前最为庞大又在快速增长的当属 React 了,本文就来重点介绍 React 的生态系统. 首 ...

  2. [国嵌笔记][011][Linux密码破解]

    破解步骤 1.在系统启动时进入grub选项菜单 2.在grub选项菜单中按e进入编辑模式 3.编辑kernel行,添加 /init 1 (表示进入单用户启动模式,在单用户启动模式中不会要求输入密码) ...

  3. 自实现PC端jQuery版轮播图

    最近其他项目不是很忙,被安排给公司的官网项目做一个新的页面(之前没接触公司官网项目),其中有一个用到轮播图的地方,最开始想直接用swiper.js插件实现就好了,可是发现官网项目里之前都没有引入过sw ...

  4. python通过scapy模块进行arp断网攻击

    前言: 想实现像arpsoof一样的工具 arp断网攻击原理: 通过伪造IP地址与MAC地址实现ARP欺骗,在网络发送大量ARP通信量.攻击者 只要持续不断发送arp包就能造成中间人攻击或者断网攻击. ...

  5. ThinkPHP5上传图片并压缩为缩略图

    使用thinkphp开发app后端中,需要实现一个处理上传图片队列的功能 这是个上传多图片保存并且需要对其中一张图片进行压缩的功能 (使用的html5 mui框架开发app,如果直接载入原图,app客 ...

  6. CUDA共享内存的使用示例

    CUDA共享内存使用示例如下:参考教材<GPU高性能编程CUDA实战>.P54-P65 教材下载地址:http://download.csdn.net/download/yizhaoyan ...

  7. 用photoshop将图片四角变成圆角

    1.用PS打开一张图片,用矩形选框工具,选出你要保留的的那一部分,"选择→修改→平滑".在弹出的选框里添入数值,值越大角就越圆. 2.然后选择"选择→反选"再按 ...

  8. Maven项目pom.xml 标签含义

    project:pom.xml文件中的顶层元素: modelVersion:指明POM使用的对象模型的版本.这个值很少改动. groupId:指明创建项目的组织或者小组的唯一标识.GroupId是项目 ...

  9. shell 学习四十五天---xargs

    当 find 产生一个文件列表时,该列表提供给另一个命令有时是很有用的.案例: $touch abc.c erd.c oiy.c $ll ./erd.c ./abc.c ./oiy.c $find - ...

  10. 2017-07-01(ifconfig ifdown ifup netstat )

    ifconfig 可以查看IP地址与子网掩码 ifdown(禁用网卡) ifdown  网络设备名 ifdown eth0 ifup (启动网卡) ifup  网络设备名 ifup  eth0 net ...