题目大意:

给你$n$个大串和$m$个询问,每次给出一个字符串$s$询问在多少个大串中出现过

好神的一道题

对$n$个大串建出广义$SAM$,建出$parent$树

把字符串$s$放到$SAM$里跑,找到能表示字符串$s$的节点$x$

问题转化为在$parent$树中,$x$节点的子树内,有多少个编号不同的$endpos$节点

把树拍扁,转化为$dfs$序

不就是在序列上跑HH的项链么,离线树状数组维护一下就好

一个节点可能有多个不同串$endpos$标记,用$vector$存一下串的编号就行了

注意索引不要写错,不要把数组开小了

 #include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 105000
#define S1 (N1<<1)
#define T1 (N1<<2)
#define ll long long
#define uint unsigned int
#define rint register int
#define il inline
#define inf 0x3f3f3f3f
#define idx(X) (X-'a')
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
} int n,m,len,tot;
char str[N1];
struct Edge{
int to[T1],nxt[T1],head[T1],cte;
void ae(int u,int v){
cte++;to[cte]=v;nxt[cte]=head[u],head[u]=cte;}
}E,Q;
struct BIT{
int sum[T1],ma;
void upd(int x,int w){
for(int i=x;i<=ma;i+=(i&(-i)))
sum[i]+=w;}
int query(int x){
int ans=;
for(int i=x;i>;i-=(i&(-i)))
ans+=sum[i];
return ans;}
}b;
namespace SAM{
int trs[S1][],pre[S1],dep[S1],la;
vector<int>ed[S1];
void init(){tot=la=;}
void reduct(){la=;}
void insert(int x,int id)
{
int p=la,q,np=++tot,nq;la=np;
dep[np]=dep[p]+;
ed[np].push_back(id);
for(;p&&!trs[p][x];p=pre[p]) trs[p][x]=np;
if(!p) pre[np]=;
else{
q=trs[p][x];
if(dep[q]==dep[p]+) pre[np]=q;
else{
pre[nq=++tot]=pre[q];
pre[q]=pre[np]=nq;
dep[nq]=dep[p]+;
memcpy(trs[nq],trs[q],sizeof(trs[q]));
for(;p&&trs[p][x]==q;p=pre[p]) trs[p][x]=nq;
}
}
}
void Build_Edge()
{
for(int i=;i<=tot;i++)
E.ae(pre[i],i);
}
int find(char *str,int L)
{
int x=;
for(int i=;i<=L;i++){
x=trs[x][idx(str[i])];
if(!x) return ;
}return x;
}
};
namespace Seq{
int st[T1],ed[T1],to[T1],ans[T1],la[T1],cnt;
void dfs1(int x)
{
st[x]=++cnt;
for(int j=E.head[x];j;j=E.nxt[j])
dfs1(E.to[j]);
ed[x]=++cnt;
to[cnt]=x;
}
void solve()
{
dfs1();
b.ma=cnt;
int x,v;
for(int i=;i<=m;i++)
{
scanf("%s",str+);
len=strlen(str+);
x=SAM::find(str,len);
if(x) Q.ae(ed[x],i);
}
for(int i=;i<=cnt;i++)
{
x=to[i];
for(int j=;j<SAM::ed[x].size();j++)
{
v=SAM::ed[x][j];
if(!la[v]) b.upd(i,),la[v]=i;
else b.upd(la[v],-),la[v]=i,b.upd(i,);
}
for(int j=Q.head[i];j;j=Q.nxt[j])
{
v=Q.to[j];
ans[v]=b.query(ed[x])-b.query(st[x]);
}
}
for(int i=;i<=m;i++)
printf("%d\n",ans[i]);
} }; int main()
{
//freopen("t2.in","r",stdin);
scanf("%d%d",&n,&m);
SAM::init();
for(int i=;i<=n;i++)
{
scanf("%s",str+);
len=strlen(str+);
for(int j=;j<=len;j++)
SAM::insert(idx(str[j]),i);
SAM::reduct();
}
SAM::Build_Edge();
Seq::solve();
return ;
}

BZOJ 2780 Sevenk Love Oimaster (后缀自动机+树状数组+dfs序+离线)的更多相关文章

  1. luogu SP8093 后缀自动机+树状数组+dfs序

    这题解法很多,简单说几个: 1. 线段树合并,时间复杂度是 $O(nlog^2n)$ 的. 2. 暴力跳 $fail,$ 时间复杂度 $O(n\sqrt n),$ 比较暴力. 3. 建立后缀树后在 $ ...

  2. 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序

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

  3. BZOJ.2434.[NOI2011]阿狸的打字机(AC自动机 树状数组 DFS序)

    题目链接 首先不需要存储每个字符串,可以将所有输入的字符依次存进Trie树,对于每个'P',记录该串结束的位置在哪,以及当前节点对应的是第几个串(当前串即根节点到当前节点):对于'B',只需向上跳一个 ...

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

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

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

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

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

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

  7. BZOJ 1103 [POI2007]大都市meg(树状数组+dfs序)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1103 [题目大意] 给出一棵树,每条边的经过代价为1,现在告诉你有些路不需要代价了, ...

  8. 【BZOJ-1103】大都市meg 树状数组 + DFS序

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2009  Solved: 1056[Submit][Sta ...

  9. POJ 3321 Apple Tree (树状数组+dfs序)

    题目链接:http://poj.org/problem?id=3321 给你n个点,n-1条边,1为根节点.给你m条操作,C操作是将x点变反(1变0,0变1),Q操作是询问x节点以及它子树的值之和.初 ...

随机推荐

  1. webpack学习笔记(2)--webpack.config.js

    3 模式 mode mode 参数设置为 development(开发模式), production(生产模式) 或 none(无),可以启用对应环境下 webpack 内置的优化.默认值为 prod ...

  2. XSS Chanllenges 6-10

    Stage #6 测试代码</xss> 存在过滤,并且也没有其他输入点,尝试构建" onmousemove="alert(document.domain),并查看源代码 ...

  3. centos7把编译安装的服务通过systemctl管理

    nginx编译安装的目录是/usr/local/nginx nginx配置文件是/usr/local/nginx/conf/nginx.conf systemctl管理的服务文件在/usr/lib/s ...

  4. Linux学习二:基于CentOS 6.5的网络配置

    查看网卡信息: ifconfig [root@hadoop01 ~]# ifconfig [正常的显示信息] eth0 Link encap:Ethernet HWaddr :0C::::5C ine ...

  5. MYSQL: sql中某一个字段内容为用逗号分割的字符串转换成多条数据

    场景: 表名:testsuer id     name 1       小红,小李,李红,小法 要结果值为: 1     小红 1     小李 1     李红 1     小法 MYSQL函数解释 ...

  6. Linux 内核管理

    Linux内核基础:Linux Kernel:  Linux内核的体积结构是单内核的,但充分借鉴了微内核设计体系的优点,为内核引入模块化机制,使得虽然是单内核,但工作在模块化的方式下,并且模块可以动态 ...

  7. selenium+java实现浏览器前进、后退和刷新

  8. Ajax发送XML请求案例

    Ajax发送XML请求需求: 根据输入的国家,输出这些国家下面的城市. 如果请求参数较多,而且请求参数的结构关系复杂,则可以考虑发送XML请求.XML请求的实质还是POST请求,只是在发送请求的客户端 ...

  9. [jQuery]ajax同步请求在方法内问题

    在函数内写$.ajax() 的成功函数中return 的值,并没有return到外层方法返回至

  10. 一个关于 UIPickerView 的 bug

    首先,我下描写叙述一下bug的发生情况: 在使用UIPickerView实现选择城市的时候.出现这样一个Bug 1.在iOS 6的系统上 2.Picker的数据上省份一栏选择了"香港&quo ...