P2336 [SCOI2012]喵星球上的点名(后缀自动机+莫队+dfs序)
名字怎么存?显然是后缀自动机辣
询问点到多少个喵喵喵其实就是
查询后缀自动机上parent树的一个子树
于是我们考虑莫队
怎么树上莫队呢
我们用dfs序处理后缀自动机上的parent树
把parent树映射到序列上
于是我们就可以愉快地莫队辣
最后怎么处理每个喵喵喵被点到的次数呢
我们在莫队的时候维护一个$Ls[i]$数组维护颜色$i$的存在时间(显然会被划分为好几段)
当颜色$i$第一次进队(队内本来没有该颜色)时,就记下$Ls[i]$
当队中最后一个颜色$i$出队时,答案就累加上$now-Ls[i]$,即为颜色$i$在这段的存在时间
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#define rint register int
using namespace std;
int read(){
char c=getchar();int x=;
while(c<''||c>'') c=getchar();
while(''<=c&&c<='') x=x*+(c^),c=getchar();
return x;
}
#define N 200005
int n,m,Len,L,R,dfn[N],siz[N],Co[N];
int tt,in[N],Ls[N],ans1[N],ans2[N],tot;
int cnt,hd[N],nxt[N],ed[N],poi[N];
struct data{int l,r,Id;}a[N];
inline bool cmp(data A,data B){
return (A.l/Len==B.l/Len)?A.r<B.r:A.l/Len<B.l/Len;
}
inline void adde(int x,int y){
nxt[ed[x]]=++cnt, hd[x]=hd[x]?hd[x]:cnt,
ed[x]=cnt, poi[cnt]=y;
}
struct Sam{
int fa[N],len[N],col[N],ed,q,Clock;
Sam(){Clock=;ed=;}
map<int,int> mp[N];
int add(int p,int x,int id){
len[++ed]=len[p]+; col[ed]=id;
for(;p&&!mp[p][x];p=fa[p]) mp[p][x]=ed;
if(!p) {fa[ed]=;return ed;}
q=mp[p][x];
if(len[q]==len[p]+){fa[ed]=q;return ed;}
len[++ed]=len[p]+; mp[ed]=mp[q];
fa[ed]=fa[q]; fa[q]=fa[ed-]=ed;
for(;mp[p][x]==q;p=fa[p]) mp[p][x]=ed;
return ed-;
}
void link(){for(rint i=;i<=ed;++i) adde(fa[i],i);}
void dfs(int x){//dfs序把parent树映射到序列上
dfn[x]=++Clock; Co[Clock]=col[x]; siz[x]=;
for(int i=hd[x];i;i=nxt[i])
dfs(poi[i]),siz[x]+=siz[poi[i]];
}
}S;
int main(){
n=read();m=read();int q,now;
for(rint i=;i<=n;++i){
q=read(); now=;
while(q--) now=S.add(now,read(),i);
q=read(); now=;
while(q--) now=S.add(now,read(),i);
}S.link(); S.dfs(); Len=sqrt(S.ed);
for(rint i=;i<=m;++i){
q=read();now=;
while(q--) now=S.mp[now][read()];
if(!now) continue;
a[++tt]=(data){dfn[now],dfn[now]+siz[now]-,i};
}
if(tt){//在映射序列上进行莫队
sort(a+,a+tt+,cmp);
for(rint i=a[].l;i<=a[].r;++i){
if(!in[Co[i]]&&Co[i]) ++tot,Ls[Co[i]]=;
++in[Co[i]];
}ans1[a[].Id]=tot; L=a[].l; R=a[].r;
for(rint i=;i<=tt;++i){
while(L<a[i].l){
--in[Co[L]];
if(!in[Co[L]]&&Co[L]) --tot,ans2[Co[L]]+=i-Ls[Co[L]];
++L;
}
while(R>a[i].r){
--in[Co[R]];
if(!in[Co[R]]&&Co[R]) --tot,ans2[Co[R]]+=i-Ls[Co[R]];
--R;
}
while(L>a[i].l){
--L;
if(!in[Co[L]]&&Co[L]) ++tot,Ls[Co[L]]=i;
++in[Co[L]];
}
while(R<a[i].r){
++R;
if(!in[Co[R]]&&Co[R]) ++tot,Ls[Co[R]]=i;
++in[Co[R]];
}
ans1[a[i].Id]=tot;
}
while(L<=R){
--in[Co[L]];
if(!in[Co[L]]&&Co[L]) --tot,ans2[Co[L]]+=tt-Ls[Co[L]]+;
++L;
}//注意最后剩下的数据要算进去
}
for(rint i=;i<=m;++i) printf("%d\n",ans1[i]);
for(rint i=;i<=n;++i) printf("%d ",ans2[i]);
return ;
}
P2336 [SCOI2012]喵星球上的点名(后缀自动机+莫队+dfs序)的更多相关文章
- P2336 [SCOI2012]喵星球上的点名(SA+莫队)
题面传送门 一道还算有点含金量的 SA 罢-- 首先按照套路我们把读入的所有字符串都粘在一起,中间用分隔符隔开并建出后缀数组出来. 我们考虑对于一个固定的字符串 \(s\),什么样的字符串 \(t\) ...
- Luogu2336 SCOI2012 喵星球上的点名 SA、莫队
传送门 一道很套路的题目 先将所有串拼在一起,两个不同的串之间放一个没有出现在任何串中的字符做分隔,然后SA 那么对于所有点名串能够点到的名字串在SA中对应一段区间 把这些区间拿出来然后莫队统计每一个 ...
- 洛咕 P2336 [SCOI2012]喵星球上的点名
洛咕 P2336 [SCOI2012]喵星球上的点名 先求出SA和height,一个点名串对应的就是一段区间,还有很多个点,就转化成了 有很多个区间,很多个点集,对每个区间计算和多少个点集有交,对每个 ...
- 洛谷 P2336 [SCOI2012]喵星球上的点名 解题报告
P2336 [SCOI2012]喵星球上的点名 题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 \(N\) 个喵星人,每个喵星人的 ...
- BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]
2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1906 Solved: 839[Submit][St ...
- BZOJ 2754: [SCOI2012]喵星球上的点名 [AC自动机+map+暴力]
2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1902 Solved: 837[Submit][St ...
- BZOJ2754: [SCOI2012]喵星球上的点名(AC自动机/后缀自动机)
Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串 ...
- BZOJ2754: [SCOI2012]喵星球上的点名(AC自动机)
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2816 Solved: 1246[Submit][Status][Discuss] Descript ...
- 洛谷P2336 [SCOI2012]喵星球上的点名(后缀数组+莫队)
我学AC自动机的时候就看到了这题,想用AC自动机结果被学长码风劝退-- 学后缀数组时又看到了这题--那就写写后缀数组做法吧 结果码风貌似比当年劝退我的学长还毒瘤啊 对所有的模式串+询问串,不同串之间用 ...
随机推荐
- Elasticsearch 搜索模块之Cross Cluster Search(跨集群搜索)
Cross Cluster Search简介 cross-cluster search功能允许任何节点作为跨多个群集的federated client(联合客户端),与tribe node不同的是cr ...
- jenkins 多用户同时触发构建—简单实用
插件:build name setter plugin 插件地址:http://updates.jenkins-ci.org/download/plugins/ 其实以上插件,不使用也可以,以上插件我 ...
- Linux:系统文件目录
目录结构 bin:命令类目录 命令 系统操作 清屏:clear.ctrl+L 进程: # $(ps -ef | grep hnlinux) //方法一 过滤出hnlinux用户进程 #kill -u ...
- Android提权漏洞CVE-2014-7920、CVE-2014-7921
- Sql之left join(左关联)、right join(右关联)、inner join(自关联)的区别
参考:https://blog.csdn.net/hj7jay/article/details/51749863
- java详解内部类
可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...
- 记无法用被动方式登录远程linux主机的原因
[环境]: linux主机:华为企业云 ftp服务端:vsftpd 客户端:ftp命令行工具,安卓端ES文件浏览器 [现象]: 在ES文件浏览器中,使用被动方式没法连接,使用主动方式可以连接,但是没法 ...
- 十 js中forEach,for in,for of循环的用法
一.一般的遍历数组的方法: var array = [1,2,3,4,5,6,7]; for (var i = 0; i < array.length; i++) { console.log(i ...
- 强化学习--DeepQnetwork 的一些改进
Double DQN 算Q值 与选Q值是分开的,2个网络. Multi-step Dueling DQN 如果更新了,即使有的action没有被采样到,也会更新Q值 Prioritized Reply ...
- Python全栈-day4-语法基础2
一.字符串 1.字符串基础 1)作用:用于描述姓名.性别.地址等信息 2)定义方式:单引号或者双引号以及三引号内添加字符 注:day3中介绍 name = 'zhang' user_name = &q ...