题意:有N个串,给出的形式是拼接给出,对于第i行:  (1,c)表示字符串i是单个字母c; (2,p,c)表示字符串i=在字符串p后面接上一个字母c。

然后给出M个提问,形式是(i,string)。问string在字符串i中出现了多少次。

思路:这类题显然是在AC自动机上乱搞。  对于询问的串建立AC自动机,BFS建立fail树;那么一个询问其实就是第i个串的位置到根的这些节点,有多少个在string节点的子树里。      即给一条链染色,然后询问一个点是子树里多少点被染色了。 为了不重不漏,  我们用回溯就可以处理了。 然后用树状数组维护DFS序下的前缀和。

具体的,对于N个串在AC自动机上跑,每跑一步对应N个字符串之一。 每跑到一个节点,就加加。 跑完子树后就减减,保证了加的部分是一条链。

#include<bits/stdc++.h>
#define pii pair<int,int>
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
vector<pii>G[maxn],Q[maxn];
vector<int>F[maxn];
int ch[maxn][],fail[maxn],ans[maxn],tot;
int in[maxn],out[maxn],times; //dfn
char s[maxn]; int sum[maxn];
void add(int x,int val){ while(x<=times) sum[x]+=val,x+=(-x)&x;}
int query(int x){ int res=; while(x){ res+=sum[x]; x-=(-x)&x; } return res;}
int add()
{
int now=,L=strlen(s);
rep(i,,L-) {
if(!ch[now][s[i]-'a']) ch[now][s[i]-'a']=++tot;
now=ch[now][s[i]-'a'];
} return now;
}
void build()
{
queue<int>q;
rep(i,,) if(ch[][i]) q.push(ch[][i]);
while(!q.empty()){
int u=q.front(); q.pop();
rep(i,,) {
if(ch[u][i]){
fail[ch[u][i]]=ch[fail[u]][i];
q.push(ch[u][i]);
}
else ch[u][i]=ch[fail[u]][i];
}
}
rep(i,,tot) F[fail[i]].push_back(i);
}
void dfs(int u)
{
in[u]=++times;
for(int i=;i<F[u].size();i++) dfs(F[u][i]);
out[u]=times;
}
void dfs(int u,int now) //u是位置,now是id
{
add(in[u],);
for(int i=;i<Q[now].size();i++){
pii t=Q[now][i];
ans[t.second]=query(out[t.first])-query(in[t.first]-);
}
for(int i=;i<G[now].size();i++){
pii t=G[now][i];
dfs(ch[u][t.first],t.second);
}
add(in[u],-);
}
int main()
{
int N,M,opt,p;
scanf("%d",&N);
rep(i,,N) {
scanf("%d",&opt);
if(opt==) p=;
else scanf("%d",&p);
scanf("%s",s);
G[p].pb(pii(s[]-'a',i));
}
scanf("%d",&M);
rep(i,,M) {
scanf("%d%s",&p,s);
Q[p].pb(pii(add(),i));
}
build();
dfs();
dfs(,);
rep(i,,M) printf("%d\n",ans[i]);
return ;
}

CodeForces - 1207G :Indie Album(AC自动机 fail树上DFS)的更多相关文章

  1. AC自动机fail树上dfs序建线段树+动态memset清空

    题意:http://acm.hdu.edu.cn/showproblem.php?pid=4117 思路:https://blog.csdn.net/u013306830/article/detail ...

  2. CF G. Indie Album AC自动机+fail树+线段树

    这个套路挺有意思的. 把 $trie$ 和 $fail$ 树都建出来,然后一起跑一跑就好了~ #include <queue> #include <cstdio> #inclu ...

  3. ac自动机fail树上按询问建立上跳指针——cf963D

    解法看着吓人,其实就是为了优化ac自动机上暴力跳fail指针.. 另外这题对于复杂度的分析很有学习价值 /* 给定一个母串s,再给定n个询问(k,m) 对于每个询问,求出长度最小的t,使t是s的子串, ...

  4. 洛谷2414(构建ac自动机fail树dfs序后遍历Trie树维护bit及询问答案)

    要点 这是一道蔡队题,看我标题行事 任意询问y串上有多少个x串,暴力找每个节点是不是结尾肯定是炸的,考虑本质:如果某节点是x的结尾,根据ac自动机的性质,x一定是此(子)串后缀.又有每个Trie节点的 ...

  5. BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树

    Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...

  6. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

  7. 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2022  Solved: 1158[Submit][Sta ...

  8. 【Codeforces163E】e-Government AC自动机fail树 + DFS序 + 树状数组

    E. e-Government time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...

  9. 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序

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

随机推荐

  1. 深入理解JVM-类加载初始化阶段-类的主动与被动引用

    JVM的类加载阶段中初始化阶段 P210 虚拟机规定的五种情况必须对类的“初始化”情况 1.遇到new.getstatic.putstatic.或invokestic 四条字节码指令时,如果类没有经过 ...

  2. golang知识精要(二)

    类型 go是**静态类型**语言,不能在运行期改变变量类型. 变量定义 使用var定义变量,自动初始化为零值: 如果提供初始值,可省略变量类型: 函数内部可使用:=定义变量. var x int // ...

  3. 定时删除10天前的Es索引

    说明 主要用在索引名为 xxxx-yyyy.MM.dd 这种,可以自定义修改下边的脚本 删除索引shell 创建 delete_es_indices_over_10_day.sh #!/bin/bas ...

  4. NOI2019网络同步赛游记

    我发的邮件**f没收到,后来去专门询问才整到一个名额(估计是嫌我太菜,参加了也是垫底) day -1 上午写了到类似随机游走的高斯消元期望dp,然后颓颓颓 下午打洛咕月赛.T1一直50pts,后来才知 ...

  5. Java学习:方法的使用与注意事项

    方法的使用与注意事项 定义一个方法的格式:public static void 方法名称(){ 方法体 } 如何调用方法,格式: 方法名称(): 方法名称的命名规则和变量一样,使用小驼峰. 方法体:也 ...

  6. golang 学习笔记 使用cmd

    package main import ( "bytes" "fmt" "os/exec" ) func main() { cmd0 := ...

  7. -Git Linux vi/vim 命令 按键 MD

    目录 目录 Linux vi/vim 简介 vi/vim 的使用 命令模式 输入模式 底线命令模式 vi/vim 使用实例 使用 vi/vim 进入一般模式 按下 i 进入输入模式,开始编辑文字 按下 ...

  8. 【spring boot】【redis】spring boot基于redis的LUA脚本 实现分布式锁

    spring boot基于redis的LUA脚本 实现分布式锁[都是基于redis单点下] 一.spring boot 1.5.X 基于redis 的 lua脚本实现分布式锁 1.pom.xml &l ...

  9. [shell] while read line 与for循环的区别

    [shell] while read line 与for循环的区别 while read line 与for循环的区别---转载整理 while read line 是一次性将文件信息读入并赋值给变量 ...

  10. laravel中hasOne、HasMany、belongsTo、belongsToMany的ORM方法

    在laravel5.4框架中,使用ORM关联方法,一对一,一对多 一对一关系,代码: user表为主表,需要向下找关联表的字段用hasOne video表为关联表,需要向上找关联表的字段用belong ...