LINK

这不原题嘛…

把所有询问串建立acacac自动机,再搞出failfailfail树

那么询问xxx串在yyy串中出现的多少次

等价于根节点到yyy的路径有多少个点沿着failfailfail边能跳到xxx

暴力跳的话复杂度太高,我们考虑在failfailfail树上搞

考虑将failfailfail边反向,也就是由长度小的指向长度大的

那么在failfailfail树上,xxx节点子树内的节点的后缀都是xxx

而我们知道子树内的dfsdfsdfs序是连续的,可以用树状数组来维护

具体操作就是,我们从tiretiretire图的根节点往下遍历

每到一个节点,就在树状数组上给这个点的failfailfail树dfsdfsdfs序加一

回溯的时候就减111

所以,我们到达节点yyy时,根节点到yyy路径上的点值都是1,其他点都是零

所以,我们就处理所有关于节点yyy的询问,这些询问的形式是

节点xxx在节点yyy中出现过多少次,这个只需要查询一下xxx在failfailfail树中的子树和即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
struct tree_array
{int sum[maxn],n;int lowbit(int x){ return x&(-x); }void add(int x,int val){for(;x<=n;x+=lowbit(x)) sum[x]+=val; }int ask(int x){int ans=0;for(;x;x-=lowbit(x)) ans+=sum[x];return ans;}
}t;
struct edge{int to,nxt,id;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int id){d[++cnt]=(edge){v,head[u],id},head[u]=cnt;}
int zi[maxn][26],vis[maxn][26],ans[maxn],id,fail[maxn],n,m;
int ID[maxn];//ID[i]表示第i次的字符串在自动机的ID[i]节点
char a[maxn];
vector<int>vec[maxn];
int dfn[maxn],low[maxn],dfu;
void dfs_failtree(int u)
{dfn[u] = ++dfu; for( auto v:vec[u] )if( !dfn[v] )   dfs_failtree(v);low[u] = dfu;
}
void get_fail()
{memcpy(vis,zi,sizeof vis );queue<int>q;for(int i=0;i<=25;i++) if( vis[0][i] ) q.push( vis[0][i] );while( !q.empty() ){int u = q.front(); q.pop();for(int i=0;i<=25;i++){if( vis[u][i] ) fail[vis[u][i]] = vis[fail[u]][i],q.push( vis[u][i] );else   vis[u][i] = vis[fail[u]][i];}}for(int i=1;i<=id;i++)vec[fail[i]].push_back( i );
}
void dfs_tire(int u)
{t.add( dfn[u],1 );for(int i=head[u];i;i=d[i].nxt ){int v = d[i].to;ans[d[i].id] = t.ask( low[v] )-t.ask( dfn[v]-1 );}for(int i=0;i<=25;i++)if( zi[u][i] )   dfs_tire( zi[u][i] );t.add( dfn[u],-1 );
}
void init()
{cin >> n;for(int i=1;i<=n;i++){int type,las;scanf("%d",&type);if( type==1 )//新建串 {scanf("%s",a+1 );int now = 0, len = strlen( a+1 );for(int j=1;j<=len;j++){if( !zi[now][a[j]-'a'] )   zi[now][a[j]-'a'] = ++id;now = zi[now][a[j]-'a'];}ID[i] = now;}else{scanf("%d%s",&las,a+1 );int now = ID[las], len = strlen( a+1 );for(int j=1;j<=len;j++){if( !zi[now][a[j]-'a'] ) zi[now][a[j]-'a'] = ++id;now = zi[now][a[j]-'a'];}ID[i] = now;}}cin >> m;//处理询问 for(int i=1;i<=m;i++){int x; scanf("%d%s",&x,a+1);int len = strlen( a+1 ), now = 0;for(int j=1;j<=len;j++){if( !zi[now][a[j]-'a'] )    zi[now][a[j]-'a'] = ++id;now = zi[now][a[j]-'a'];}add( ID[x],now,i );}
}
int main()
{init();t.n = id+1;get_fail(); dfs_failtree(0);dfs_tire(0);for(int i=1;i<=m;i++)   cout << ans[i] << endl;
}

CF1207G Indie Album(ACAM建fail树查询s在t出现几次)相关推荐

  1. P5357 【模板】AC自动机(二次加强版)(AC自动机建fail树dfs求模式串出现次数)

    P5357 [模板]AC自动机(二次加强版)(AC自动机建fail树dfs求模式串出现次数) 传送门 形式上,AC 自动机基于由若干模式串构成的 Trie 树,并在此之上增加了一些 fail 边:本质 ...

  2. CodeForces - 1437G Death DBMS(AC自动机fail树上树链剖分建线段树/暴跳fail)

    题目链接:点击查看 题目大意:给出 n 个模式串,每个模式串初始时的权值为 0,然后有 m 次操作: 1 i x:将第 i 个模式串的权值修改为 x 2 s:给出一个字符串 s,询问字符串 s 作为主 ...

  3. BZOJ 2434: [Noi2011]阿狸的打字机 ACAM+fail树

    title BZOJ 2434 LUOGU 2414 Description 打字机上只有 \(28\) 个按键,分别印有 \(26\) 个小写英文字母和 B.P 两个字母,是这样工作的: 输入小写字 ...

  4. hdu4117 GRE Words(ACAM+fail树+线段树)

    首先我们有如果i< j,且sisis_i为sjsjs_j的子串,那么有转移f[j]=f[i]+w[j]f[j]=f[i]+w[j]f[j]=f[i]+w[j] 其中f[i]f[i]f[i]表示以 ...

  5. CF-1207 G.Indie Album(Trie上跑AC自动机)

    CF-1207 G.Indie Album(Trie上跑AC自动机) 题目链接 题意 nnn个串,串的生成方式有两种: 单独一个字符 在上一个串的基础上加一个字符 qqq个询问,问第iii个串中出现串 ...

  6. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 2545  Solved: 1419 [Submit][S ...

  7. fail树(bzoj 3172: [Tjoi2013]单词)

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 4223  Solved: 2051 [Submit][Stat ...

  8. HDU - 7084 Pty loves string kmp + fail树 + 主席树

    传送门 文章目录 题意: 思路: 题意: 给你一个字符串sss,有qqq个询问,每次给x,yx,yx,y代表取sss的前xxx个字符和后yyy个字符拼接起来得到ttt,输出ttt在sss中出现的次数. ...

  9. bzoj 2434 [Noi2011]阿狸的打字机(AC自动机+fail树+dfs序+树状数组)

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 3521  Solved: 1913 [Submit][S ...

最新文章

  1. 纠结的名字 - 自动生成apk文件名
  2. android中完全退出当前应用程序的四种方法
  3. 【人物】李开复:未来属于创新者和小公司
  4. Java黑皮书课后题第6章:**6.24(显示当前日期和时间)程序清单2-7显示当前时间。改进这个例子,显示当前的日期和时间。程序清单6-12中的日历例子可以提供一些如何提供如何求年月日的思路
  5. 如何把一个java工程打成一个jar包(转载)
  6. 风靡全球的人工智能,如何赶上这班车?
  7. 移动硬盘提示无法访问设备硬件出现致命错误,导致请求失败的资料寻回方案
  8. 配置iscsi服务器_在Windows Server 2016上安装和配置iSCSI目标服务器
  9. HDU - 3564 Another LIS(LIS+线段树)
  10. 【学堂在线数据挖掘:理论方法笔记】第八天(4.2)
  11. 考试管理系统【软件工程实践课设报告】
  12. django常见面试题
  13. 公众号粉丝迁移需要多长时间?
  14. vue 调用虚拟键盘
  15. 【雅思大作文考官范文】——第十七篇: 'economic progress' essay
  16. V2X测试系列——V2X应用场景仿真及开发流程
  17. POJ 1392 Ouroboros Snake 欧拉回路
  18. 16张SIM卡,8路5g多卡聚合路由器5g多卡汇聚路由器,多网融合,弱网通信
  19. mmdetection使用
  20. TCP/IP模型背后的内涵(一)

热门文章

  1. Android--adb命令详解
  2. 全国计算机信息安全学院排名,2021年中国信息安全专业大学排名「大学专业排名」...
  3. MySQL日期时间带T_Mysql 时间和日期函数
  4. 数组对象去重(vue)
  5. webpack resolve的作用
  6. Linux操作命令(三)
  7. 不要随意使用手形光标
  8. JS数组去重之indexOf去重
  9. 表达爱情html,表达爱意的爱情句子
  10. Mysql----基础