给定n个串m个询问,问每个串在n个串多少个串中出现了。

构建广义后缀自动机,(就是把所有字符串的后缀自动机合并起来)其实只需要add的时候注意一下就可以了。

然后对于每一个串,跑一边匹配,到达了now点。

如果now等于零,那么无法匹配,为0

否则就是询问子树中属于不同的后缀的节点又多少个。

如果n的数目比较小,可以考虑O(nl)去树形DP

我们只能,用vector打上标记。

然后dfs序搞出来,然后就是区间不同数的计数问题,然后直接《HH的项链》这道题目一套就可以了。

这一题套一题确实很有趣,代码丑到爆炸

#include <map>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define maxn 500005 int in[maxn],out[maxn],tot,lst[maxn],ans[maxn];
int arr[maxn],pos[maxn],top,nxt[maxn]; struct Query{
int l,r,id;
void print()
{
printf("Query About %d to %d\n",l,r);
}
}brr[maxn]; struct Generalized_Suffix_Automaton{
int h[maxn],to[maxn],ne[maxn],en;
char s[maxn];
int last,cnt,n,q;
map<int,int>go[maxn];
int l[maxn],fa[maxn];
vector<int>v[maxn];
void init(){last=cnt=1;memset(h,-1,sizeof h);}
void addedge(int a,int b)
{to[en]=b;ne[en]=h[a];h[a]=en++;}
void add(int x,int id)
{
int p=last,q;
if (q=go[p][x])
{
if (l[p]+1==l[q]) last=q;
else
{
int nq=++cnt; l[nq]=l[p]+1;
go[nq]=go[q];
fa[nq]=fa[q];
fa[q]=nq;
for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
last=nq;
}
}
else
{
int np=++cnt;
l[np]=l[p]+1;
for (;p&&!go[p][x];p=fa[p]) go[p][x]=np;
if (!p) fa[np]=1;
else
{
q=go[p][x];
if (l[q]==l[p]+1) fa[np]=q;
else
{
int nq=++cnt;l[nq]=l[p]+1;
go[nq]=go[q];
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
}
}
last=np;
}
v[last].push_back(id);
}
void dfs(int k)
{
in[k]=++tot;
for (int i=0;i<v[k].size();++i) arr[++tot]=v[k][i];
for (int i=h[k];i>=0;i=ne[i]) dfs(to[i]);
out[k]=tot;
}
void solve()
{
init();
scanf("%d%d",&n,&q);
F(i,1,n)
{
last=1;
scanf("%s",s+1);
int len=strlen(s+1);
F(j,1,len) add(s[j],i);
}
F(i,1,cnt) addedge(fa[i],i);
dfs(1);
F(i,1,q)
{
scanf("%s",s+1);
int len=strlen(s+1);
// printf("%s\n",s+1);
// F(j,1,len) printf("-%c-",s[j]); printf("\n");
int now=1;
F(j,1,len){now=go[now][s[j]];}
// printf("now is %d\n",now);
if (now)
{
++top;
brr[top].l=in[now];
brr[top].r=out[now];
brr[top].id=i;
}
}
}
}sam; struct Bit_Tree{
int x[maxn];
void add(int pos,int del)
{for (;pos<=tot;pos+=pos&(-pos)) x[pos]+=del;}
int query(int pos)
{int ret=0;for (;pos;pos-=pos&(-pos))ret+=x[pos];return ret;}
}BT; bool cmp(Query a,Query b)
{return a.l==b.l?a.r<b.r:a.l<b.l;} int main()
{
sam.solve();
// F(i,1,tot) printf("%d ",arr[i]); printf("\n");
// F(i,1,top) brr[i].print();
sort(brr+1,brr+top+1,cmp);
F(i,1,tot)
{
if (!lst[arr[i]]) BT.add(i,1);
else nxt[lst[arr[i]]]=i;
lst[arr[i]]=i;
}
int Added=1;
F(i,1,top)
{
while (Added<brr[i].l)
{
if (nxt[Added]&&arr[nxt[Added]]) BT.add(nxt[Added],1);
Added++;
}
ans[brr[i].id]=BT.query(brr[i].r)-BT.query(brr[i].l-1);
}
F(i,1,sam.q) printf("%d\n",ans[i]);
}

  

BZOJ 2780 [Spoj]8093 Sevenk Love Oimaster ——广义后缀自动机的更多相关文章

  1. bzoj 3277 串 && bzoj 3473 字符串 && bzoj 2780 [Spoj]8093 Sevenk Love Oimaster——广义后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3277 https://www.lydsy.com/JudgeOnline/problem.p ...

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

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

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

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

  4. 三种做法:BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster

    目录 题意 思路 AC_Code1 AC_Code2 AC_Code3 参考 @(bzoj 2780: [Spoj]8093 Sevenk Love Oimaster) 题意 链接:here 有\(n ...

  5. BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster( 后缀数组 + 二分 + RMQ + 树状数组 )

    全部串起来做SA, 在按字典序排序的后缀中, 包含每个询问串必定是1段连续的区间, 对每个询问串s二分+RMQ求出包含s的区间. 然后就是求区间的不同的数的个数(经典问题), sort queries ...

  6. bzoj 2780 [Spoj]8093 Sevenk Love Oimaster

    LINK:Sevenk Love Oimaster 询问一个模式串在多少个文本串中出现过. 考虑广义SAM 统计这种数量问题一般有三种做法. 一种 暴力bitset 这道题可能可以过? 一种 暴力跳p ...

  7. bzoj 2780: [Spoj]8093 Sevenk Love Oimaster(广义SAM)

    题目大意:给出n个原串,再给出m个查询串.求每个查询串出现在了多少原串中. 题解 直接对原串建一个广义SAM,然后把每一个原串放到SAM上跑一跑,记录一下每一个状态属于多少个原串,用$size$表示. ...

  8. bzoj 2780: [Spoj]8093 Sevenk Love Oimaster【广义SAM】

    AC自动机比较简单,把询问串做成AC自动机然后模板串边跑变更新即可 SAM是把模板串做成广义SAM,然后每个节点存有几个模板串经过,具体方法是每次更新暴力向上跳直到有时间戳我不会证为什么时间复杂度是对 ...

  9. 【刷题】BZOJ 2780 [Spoj]8093 Sevenk Love Oimaster

    Description Oimaster and sevenk love each other. But recently,sevenk heard that a girl named ChuYuXu ...

随机推荐

  1. github入门之配置github本地仓库--2

    *前期准备工作 创建github账户 github地址 1.设置SSH_Key ssh-keygen -t rsa -C "你的邮箱" 2.查看秘钥 cat ~/.ssh/id_r ...

  2. The - Modcrab——使用贪心策略

    一.题目信息 The - Modcrab 简单翻译一下:Vova有生命值h1,每次攻击值为a1,每瓶药水恢复生命值c1;Modcrab有生命值h2,每次攻击值为a2.在每个关卡开始,Vova有两种选择 ...

  3. for循环输出i为同一值的问题

    使用闭包将变量i的值保护起来. //sava1:加一层闭包,i以函数参数形式传递给内层函数 for( var i=0; i<ps.length; i++ ) { (function(arg){ ...

  4. 用cssText批量修改样式

    一般情况下我们用js设置元素对象的样式会使用这样的形式: var element= document.getElementById(“id”);element.style.width=”20px”;e ...

  5. 利用python进行数据分析1_numpy的基本操作,建模基础

    import numpy as np # 生成指定维度的随机多维数据 data=np.random.rand(2,3) print(data) print(type(data)) 结果: [[0.11 ...

  6. 数据库_8_SQL基本操作——数据操作

    SQL基本操作——数据操作 一.新增数据(两种方案) 方案1: 给全表字段插入数据,不需要指定字段列表,要求数据的值出现的顺序必须与表中设计的字段出现的顺序一致,凡是非数值数据,都需要使用引号(建议是 ...

  7. CPP-网络/通信:WebService

    工具:vc2003 //引入相关头文件,连接动态库,定义全局变量. //***************************************************** #include & ...

  8. ios之coredata(二)

    上面一篇文章介绍了coredata的有关基本概念,由于大部分是参考别人文章中的内容,所以感觉有点虚,而且估计也是比较难以理解,下面这篇文章通俗一点说说学习coredata后的一些理解,然后给出一个简单 ...

  9. Swift 中 String 与 CChar 数组的转换

    在现阶段Swift的编码中,我们还是有很多场景需要调用一些C函数.在Swift与C的混编中,经常遇到的一个问题就是需要在两者中互相转换字符串.在C语言中,字符串通常是用一个char数组来表示,在Swi ...

  10. HDU-1217-Arbitrage(SPFA)

    这题和以往的求最短路的题目略微有点不一样,以往求的都是最小的,这题求的是大的,而且还是乘法. 我们求的时候初始化的时候就要进行相反的初始化了,把它们初始化为0,然后比较大的就更新. 因为这题的点少边多 ...