题目大意,给出两个字符串集合S和T,向T中添加字符串,查询S_i在T中有几个字符串出现过。一看这种多字符串匹配问题,我们联想到了AC自动机,做法就是,对于S集合我们建立一个AC自动机,建出fail树,fail树有一个很好的性质就是,对于一个节点x,它所对应的字符串是它子树中所有节点对应的字符串的后缀。我们考虑如果S_x在P_x 中出现过,他肯定是P_x某一个前缀的后缀,所以我们把P_x在AC自动机上跑,跑到每一个节点我们更新一下他所在的fail树,统计答案的时候只需统计子树的大小就行了。但是这样会有一点小问题,就是会统计重复,如果对于每一个前缀我们都更新一下它到跟的路径和,这样会重复,因为S_x可能会在P_x中出现多次。实际上我们求的是一个点的子树所有链的并集,解决方案很巧妙,利用树上差分,我们按照dfs序排好顺序,然后相邻的两个节点的lca处-1就行了,这样就不会统计重复,利用树状数组维护一下dfs序即可。(有一点需要注意,在trie树上我们一共有tot个节点,那么对于fail树我们有tot+1个节点,树状数组大小注意一下,一开始错在了这里)——by VANE

#include<bits/stdc++.h>
using namespace std;
const int N=2000010;
char s[N];
vector<int> g[N];
int son[N][30],fail[N],L[N],R[N],a[N];
int sum[N],pos[N],id[N],dep[N];
int mn[N*2][25],LOG[N*2];
int tot,n,dfn,cnt;
int cmp(int x,int y)
{return L[x]<L[y];
}
void dfs(int u)
{L[u]=++dfn;mn[pos[u]=++cnt][0]=u;for(int i=0;i<g[u].size();++i){int v=g[u][i];dep[v]=dep[u]+1;dfs(v);mn[++cnt][0]=u;}R[u]=dfn;
}
void insert(int x)
{int l=strlen(s+1);int p=0;for(int j=1;j<=l;++j){if(!son[p][s[j]-'a']) son[p][s[j]-'a']=++tot;p=son[p][s[j]-'a'];}id[x]=p;
}
void getfail()
{queue<int> q;for(int i=0;i<26;++i)if(son[0][i]) q.push(son[0][i]);while(!q.empty()){int u=q.front();q.pop();for(int i=0;i<26;++i)if(son[u][i])fail[son[u][i]]=son[fail[u]][i],q.push(son[u][i]);else son[u][i]=son[fail[u]][i];}
}
int query(int x)
{int res=0;for(;x;x-=x&-x)res+=sum[x];return res;
}
int lca(int x,int y)
{if(pos[x]<pos[y]) swap(x,y);int len=pos[x]-pos[y]+1;len=LOG[len];return min(mn[pos[y]][len],mn[pos[x]-(1<<len)+1][len],cmp);
}
void add(int x,int w)
{for(;x<=tot+1;x+=x&-x)sum[x]+=w;
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;++i){scanf("%s",s+1);insert(i);}getfail();for(int i=1;i<=tot;++i) g[fail[i]].push_back(i);dfs(0);for(int k=1;(1<<k)<=cnt;++k) LOG[1<<k]=k;for(int i=3;i<=cnt;++i)if(!LOG[i]) LOG[i]=LOG[i-1];for(int k=1;k<=LOG[cnt];++k)for(int i=1;i+(1<<k)-1<=cnt;++i)mn[i][k]=min(mn[i][k-1],mn[i+(1<<k-1)][k-1],cmp);int q;scanf("%d",&q);while(q--){int opt;scanf("%d",&opt);if(opt==1){scanf("%s",s+1);int l=strlen(s+1);int p=0;for(int i=1;i<=l;++i)a[i]=p=son[p][s[i]-'a'];sort(a+1,a+1+l,cmp);for(int i=1;i<=l;++i)add(L[a[i]],1);for(int i=1;i<l;++i){int x=lca(a[i],a[i+1]);add(L[x],-1);}}else{int x;scanf("%d",&x);printf("%d\n",query(R[id[x]])-query(L[id[x]]-1));}}
}

转载于:https://www.cnblogs.com/nbwzyzngyl/p/8331345.html

BZOJ3881 Coci2015 Divljak fail树+差分相关推荐

  1. LCA 朴素算法+树差分倍增+Tarjan算法 三种算法实现c++代码实现

    哔哩哔哩up视频:https://www.bilibili.com/video/BV1nE411L7rz?t=379 转载:http 文章目录 树差分 & 倍增LCA Tarjan 朴素算法 ...

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

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

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

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

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

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

  5. 洛谷P5357 - 【模板】AC自动机(二次加强版)(AC自动机+fail树)

    题目链接:点击查看 题目大意:给出n个模式串,问在主串中分别出现了多少次 题目分析:如果像以往那样,在匹配的时候fail指针乱跳的话,那么是错误的AC自动机使用方法,时间复杂度也大大上升,接近于暴力的 ...

  6. [Coci2015]Divljak

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

  7. bzoj 1535: [POI2005]Sza-Template(fail树)

    1535: [POI2005]Sza-Template Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 372  Solved: 195 [Submit] ...

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

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

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

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

  10. [POI2005][luogu3462] SZA-Template [fail树]

    题面 传送门 思路 首先,我们观察一下这个要求的"模板串",发现它有如下性质: 1.一个模板串$A$是要求的文本串$B$的公共前后缀 2.如果一个模板串$A$有另一个模板串$B$( ...

最新文章

  1. [转] 一个OpenSource的评价图
  2. SpringMVC如何获取请求带来的各种信息 ||如果我们的请求参数是一个POJO(自定义参数类型), SpringMVC会自动的为这个POJO进行赋值
  3. oracle默认初始化用户名密码和密码修改
  4. JS如何制作图形验证码
  5. 没有mmu可以跑Linux吗?
  6. 7-4 统计一行文本的单词个数 (15 分)
  7. Java 14 有哪些新特性?
  8. 【渝粤教育】国家开放大学2018年秋季 0455-22T物流实务 参考试题
  9. 2.4.PHP7.1 狐教程-【PHP常量】
  10. 2.5A双路电机驱动模块 正反转 PWM调速 双H桥 步进电机 超L298N
  11. 智能门锁与网关:海康萤石智能门锁的网关分析(二)
  12. 深信服测试开发日常实习岗位一面凉经(来自李某)
  13. MVC无法打开项目文件 此安装不支持该项目类型
  14. 计算机VB语言VERSION,怎么用VB获得电脑中excel的版本号
  15. 06 体脂率案例优化
  16. JAVA仓库管理系统(附源码+调试)
  17. 自动驾驶--高精地图技术
  18. 什么是聚合支付?聚合支付的优势?
  19. [机器学习] 模型融合GBDT(xgb/lgbm/rf)+LR 的原理及实践
  20. ckplayer播放器的style.zip(干货)

热门文章

  1. Linux系统下编译连接C源代码
  2. poj3083Children of the Candy Corn(dfs+bfs)
  3. Gdcm源码编译with python wrap详解
  4. 人生小故事,看完后想十秒钟,你会获益匪浅
  5. Portable SharpDevelop(PSD):便携的DotNet集成开发环境
  6. pycharm 调试教程
  7. AAAI'22 | 中稿的论文网友找出致命漏洞?
  8. 【收藏】图解最常用的10个机器学习算法!
  9. 【NLP入门】通俗讲解Subword Models
  10. 模型调参(AutoML)— optuna