BZOJ 2780 Sevenk Love Oimaster (后缀自动机+树状数组+dfs序+离线)
题目大意:
给你$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序+离线)的更多相关文章
- luogu SP8093 后缀自动机+树状数组+dfs序
这题解法很多,简单说几个: 1. 线段树合并,时间复杂度是 $O(nlog^2n)$ 的. 2. 暴力跳 $fail,$ 时间复杂度 $O(n\sqrt n),$ 比较暴力. 3. 建立后缀树后在 $ ...
- 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序
[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...
- BZOJ.2434.[NOI2011]阿狸的打字机(AC自动机 树状数组 DFS序)
题目链接 首先不需要存储每个字符串,可以将所有输入的字符依次存进Trie树,对于每个'P',记录该串结束的位置在哪,以及当前节点对应的是第几个串(当前串即根节点到当前节点):对于'B',只需向上跳一个 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- BZOJ 3881 [Coci2015]Divljak(AC自动机+树状数组)
建立AC自动机然后,加入一个串之后考虑这个串的贡献.我们把这个串扔到AC自动机里面跑.最后对经过每一个点到的这个点在fail树的根的路径上的点有1的贡献.求链的并,我们把这些点按DFS序排序,然后把每 ...
- 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序
3881: [Coci2015]Divljak Time Limit: 20 Sec Memory Limit: 768 MBSubmit: 508 Solved: 158[Submit][Sta ...
- BZOJ 1103 [POI2007]大都市meg(树状数组+dfs序)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1103 [题目大意] 给出一棵树,每条边的经过代价为1,现在告诉你有些路不需要代价了, ...
- 【BZOJ-1103】大都市meg 树状数组 + DFS序
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2009 Solved: 1056[Submit][Sta ...
- POJ 3321 Apple Tree (树状数组+dfs序)
题目链接:http://poj.org/problem?id=3321 给你n个点,n-1条边,1为根节点.给你m条操作,C操作是将x点变反(1变0,0变1),Q操作是询问x节点以及它子树的值之和.初 ...
随机推荐
- 网上的CSS例子编写都不太严谨,如*{ margin:0;padding:0;}
margin:0;padding:0; 一般情况下不可以用 *{margin:0;padding:0;} 来适配. 保证自己的严谨代码编写风格.
- Project Euler 38 Pandigital multiples
题意: 将192分别与1.2.3相乘: 192 × 1 = 192192 × 2 = 384192 × 3 = 576 连接这些乘积,我们得到一个1至9全数字的数192384576.我们称192384 ...
- MYSQL数据库常用的LINUX命令
此为我工作中常用MYSQL数据库命令 LINUX系统中启动 / 重启MYSQL服务:service mysql start / service mysql restart(重启服务) LINUX系 ...
- [剑指offer] 29. 顺时针打印矩阵 (for循环条件)
思路: 先定义左上和右下角点坐标,打印可分为从左到右,从上到下,从右到左,从下到上.依次判断最后一圈的四个循环条件. #include "../stdafx.h" #include ...
- Mybatis拦截器执行过程解析
上一篇文章 Mybatis拦截器之数据加密解密 介绍了 Mybatis 拦截器的简单使用,这篇文章将透彻的分析 Mybatis 是怎样发现拦截器以及调用拦截器的 intercept 方法的 小伙伴先按 ...
- 0113针对大数据量SUM的优化-思路
转自博客:http://bbs.csdn.net/topics/390426801?page=1 优化思路:无论如何你的结果都是要扫描全有表记录,而在456010记录中,的UserName的分布导致这 ...
- CF802G Fake News (easy)
CF802G Fake News (easy) 题意翻译 给定一个字符串询问能否听过删除一些字母使其变为“heidi” 如果可以输出“YES”,不然为“NO” 题目描述 As it's the fir ...
- 看云-git类的书籍写作
看云-git类的书籍写作 https://www.kancloud.cn/explore 测试一本:https://www.kancloud.cn/stono/b001/501901
- Linux Unix shell 编程指南学习笔记(第三部分)
第十三章 登陆环境 登陆系统时.输入username和password后.假设验证通过.则进入登录环境. 登录过程 文件/etc/passwd $HOME.profile 定制$HOME.profi ...
- 零基础学python-7.7 字符串格式化方法(1)
承接上一章节.我们这一节来说说字符串格式化的还有一种方法.就是调用format() >>> template='{0},{1} and {2}' >>> templ ...