怎么全是广义后缀自动机,我\(AC\)自动机不服

这道题可以使用的算法很多,\(SA\)或者\(SAM\)应该都可以

但是我都不会

但是这毕竟是一个多串匹配问题,\(AC\)自动机还是可以刚一刚的

我们先考虑一下暴力做法

先将操作离线下来,之后对于所有的询问串建立\(AC\)自动机,之后我们把\(n\)个给出串放到\(AC\)自动机上跑一遍,统计一下有多少个询问串可以是其子串,给这些询问串打上标记,最后输出每一个询问串被打了几次标记就好了

但是这个做法需要我们暴力去跳\(fail\)指针,于是很容易被卡成平方级别

思考一下跳\(fail\)的实质就是在\(fail\)树上暴力从当前点访问到根,而最后的查询也只是查询一个子树内部不同的标记数

于是我们熟练地想到了把\(fail\)树抽离出来,现在的问题转化为一个子树内部有多少个不同颜色的标记

是不是非常眼熟,这不就是HH的项链多了个\(dfs\)序吗

于是现在莫队或者树状数组都可以上了,不过可以树状数组谁写莫队啊

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#define re register
#define maxn 360005
#define lowbit(x) ((x)&(-x))
int n,m,num,__,cnt;
struct E {int v,nxt;}e[maxn<<1];
struct Ask{int x,y,rk;}a[maxn];
char S[maxn];
std::string s[10005];
std::vector<int> v[maxn],pre[maxn];
int son[360005][26],fail[maxn],to[maxn];
int deep[maxn],dfn[maxn],head[maxn],sum[maxn],lst[maxn];
int c[maxn],f[maxn],E[100005],Ans[maxn];
inline void add_edge(int x,int y){e[++num].v=y,e[num].nxt=head[x],head[x]=num;}
inline int add(int x,int val){for(re int i=x;i<=__;i+=lowbit(i)) c[i]+=val;}
inline int ask(int x){int ans=0;for(re int i=x;i;i-=lowbit(i)) ans+=c[i];return ans;}
inline void ins(int x)
{
int now=0;
scanf("%s",S+1);
int len=strlen(S+1);
for(re int i=1;i<=len;i++)
{
if(!son[now][S[i]-'a']) son[now][S[i]-'a']=++cnt;
now=son[now][S[i]-'a'];
}
E[x]=now;
}
inline void Build()
{
std::queue<int> q;
for(re int i=0;i<26;i++) if(son[0][i]) q.push(son[0][i]);
while(!q.empty())
{
int k=q.front();
q.pop();
if(k) add_edge(fail[k],k);
for(re int i=0;i<26;i++)
if(son[k][i]) fail[son[k][i]]=son[fail[k]][i],q.push(son[k][i]);
else son[k][i]=son[fail[k]][i];
}
}
void dfs(int x)
{
dfn[++__]=x,to[x]=__;
sum[x]=1;
for(re int i=head[x];i;i=e[i].nxt)
if(!deep[e[i].v])
{
deep[e[i].v]=deep[x]+1;
dfs(e[i].v);
sum[x]+=sum[e[i].v];
}
}
inline void query(int x)
{
int len=s[x].size();
int now=0;
for(re int i=0;i<len;i++)
{
now=son[now][s[x][i]-'a'];
if(!f[now]) v[now].push_back(x);
if(!f[fail[now]])
v[fail[now]].push_back(x);
f[fail[now]]=f[now]=1;
}
now=0;
for(re int i=0;i<len;i++)
{
now=son[now][s[x][i]-'a'];
f[now]=f[fail[now]]=0;
}
}
inline int cmp(Ask A,Ask B){return A.y<B.y;}
int main()
{
scanf("%d%d",&n,&m);
for(re int i=1;i<=n;i++) std::cin>>s[i];
for(re int i=1;i<=m;i++) ins(i);
Build(),deep[0]=1,dfs(0);
for(re int i=1;i<=n;i++) query(i);
for(re int i=1;i<=m;i++) a[i].x=to[E[i]],a[i].y=to[E[i]]+sum[E[i]]-1,a[i].rk=i;
std::sort(a+1,a+m+1,cmp);
for(re int i=1;i<=__;i++)
for(re int j=0;j<v[dfn[i]].size();j++)
pre[i].push_back(lst[v[dfn[i]][j]]),lst[v[dfn[i]][j]]=i;
int top=1;
for(re int i=1;i<=__;i++)
{
for(re int j=0;j<pre[i].size();j++)
{
add(i,1);
if(pre[i][j])
add(pre[i][j],-1);
}
while(a[top].y==i)
Ans[a[top].rk]=ask(a[top].y)-ask(a[top].x-1),top++;
}
for(re int i=1;i<=m;i++) printf("%d\n",Ans[i]);
return 0;
}

SPOJ8093【JZPGYZ - Sevenk Love Oimaster】的更多相关文章

  1. SP8093 JZPGYZ - Sevenk Love Oimaster 解题报告

    SP8093 JZPGYZ - Sevenk Love Oimaster 题目大意 给定\(n(n\le 10000)\)个模板串,以及\(m(m\le 60000)\)个查询串(模板串总长\(\le ...

  2. 【洛谷 SP8093】 JZPGYZ - Sevenk Love Oimaster(后缀自动机)

    题目链接 广义sam.. #include <cstdio> #include <cstring> #include <algorithm> using names ...

  3. SPOJ 8093 JZPGYZ - Sevenk Love Oimaster

    思路 可以用复杂度不对的做法水过去 相当于求parent树子树中的颜色种数,可以离线后树状数组(HH的项链,询问右端点排序之后维护last),dsu on tree,莫队都可以 但是也可以记录每个点上 ...

  4. SP8093 JZPGYZ - Sevenk Love Oimaster(广义后缀自动机)

    题意 题目链接 Sol 广义后缀自动机板子题..和BZOJ串那个题很像 首先建出询问串的SAM,然后统计一下每个节点被多少个串包含 最后直接拿询问串上去跑就行了 #include<bits/st ...

  5. SP8093 JZPGYZ - Sevenk Love Oimaster(SAM)

    /* 打模板题啊 每个串影响到的集合直接枚举跳parent处理即可 */ #include<cstdio> #include<algorithm> #include<cs ...

  6. SP8093 JZPGYZ - Sevenk Love Oimaster

    传送门 广义后缀自动机-- 其实也不是很难理解,就是每次SAM插入一个串之后,插入新的串的时候,要把last重新调到1的位置,共用一些节点. 这个题我们首先要预处理出来每个状态被多少个串共用.挺暴力的 ...

  7. BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster [广义后缀自动机]

    JZPGYZ - Sevenk Love Oimaster     Oimaster and sevenk love each other.       But recently,sevenk hea ...

  8. 【BZOJ2780】【SPOJ】Sevenk Love Oimaster(后缀自动机)

    [BZOJ2780][SPOJ]Sevenk Love Oimaster(后缀自动机) 题面 BZOJ 洛谷 题解 裸的广义后缀自动机??? 建立广义后缀自动机建立出来之后算一下每个节点被几个串给包括 ...

  9. 【BZOJ2780】[Spoj]8093 Sevenk Love Oimaster 广义后缀自动机

    [BZOJ2780][Spoj]8093 Sevenk Love Oimaster Description Oimaster and sevenk love each other.     But r ...

随机推荐

  1. Xtts v4变化&先决条件&已知问题

    V4变化的主要有:     1.这个采购使用简化的命令.源的一个命令(--backup)和目标的一个命令(--restore). 2.此过程只需要在源和目标的$ TMPDIR(res.txt)之间复制 ...

  2. MAC 下 STF 的环境搭建和运行

    STF --WEB 端批量移动设备管理控制工具 安装各种包 (首先安装Macport,因为后面需要用到port:http://www.ccvita.com/434.html) linux的基本包安装, ...

  3. 腾讯毛华:智能交互,AI助力下的新生态

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 演讲人:毛华 腾讯云语音云总经理 背景:5月23-24日,以"焕启"为主题的腾讯"云+未来"峰会在广 ...

  4. SpringSecurity 3.2入门(10)自定义权限控制认证及授权的过程

    上一章的代码实现还存在一些问题,如角色表.权限表的用处没有体现出来,但是已经能完成URL拦截功能,后面将会继续完善认证及授权的过程. 认证及授权的过程如下: 1.容器启动,MyInvocationSe ...

  5. 运算符重载关键字operator

    operator关键字用来重载内置运算符,使用方法如下: public class OperatorController : Controller { // // GET: /Operator/ pu ...

  6. 【转载】BootStrap表格组件bootstrap table详解

    (转载,来源“脚本之家”,作者不详) 一.Bootstrap Table的引入 关于Bootstrap Table的引入,一般来说还是两种方法: 1.直接下载源码,添加到项目里面来.由于Bootstr ...

  7. springmvc 登陆拦截器 配合shiro框架使用

    public class LoginHandlerInterceptor extends HandlerInterceptorAdapter{ @Override public boolean pre ...

  8. Python爬虫之三种数据解析方式

    一.引入 二.回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需 ...

  9. 【linux学习笔记】began,每次玩这个都特别着迷

    胡乱的安装,通过虚拟机,从DVD加载开始,当然网上有大段的装机教程,装了两个Linux发行版,一个是centos7,一个是ubuntu18.04. 分区那些事: 因为处于学习阶段,所以总是因为分区问题 ...

  10. 巡风扫描器安装-windows部署

    巡风是一款适用于企业内网的漏洞快速应急,巡航扫描系统. 作者github地址 https://github.com/ysrc/xunfeng 一.环境安装 1,安装Python解释器 https:// ...