洛谷P2336 [SCOI2012]喵星球上的点名(后缀数组+莫队)
我学AC自动机的时候就看到了这题,想用AC自动机结果被学长码风劝退……
学后缀数组时又看到了这题……那就写写后缀数组做法吧 结果码风貌似比当年劝退我的学长还毒瘤啊
对所有的模式串+询问串,不同串之间用不同分隔符隔开,然后建后缀数组
第一问,显然所有包含询问串的后缀们的排名是一段连续的区间。于是就可以用ST表处理每两个后缀间的最长公共前缀,然后二分左端点和右端点。于是就变成了一个模板得不能再模板的,数一个区间中出现了多少个不同的数的莫队
第二问,考虑差分:每次询问时,如果一个串第一次出现,加上这个询问之后的询问个数,如果这个串将被删除,减掉这个询问之后的询问个数
代码:
#include <bits/stdc++.h>
#define M 420005
#define rep(i,x,y) for(i=(x);i<=(y);++i)
using namespace std;
int id[M],bg[M],n,m,sz=11000,ll[M];
namespace SA{
int tp[M],tax[M],rnk[M],sa[M],height[M],len=0;
int f[M][20],name[M];
void init(){
int i,j,x,y;
scanf("%d%d",&n,&m);
rep(i,1,n){
rep(j,0,1){
scanf("%d",&x);
while(x--){
scanf("%d",&y);y++;
name[++len]=y,id[len]=i;
}
name[++len]=++sz;
if(!j) id[len]=i;
}
}
rep(i,1,m){
scanf("%d",&x);
ll[i]=x,bg[i]=len+1;
while(x--){
scanf("%d",&y);y++;
name[++len]=y;
}
name[++len]=++sz;
}sz++;
}
void Qsort(){
int i;
rep(i,0,sz) tax[i]=0;
rep(i,1,len) tax[rnk[i]]++;
rep(i,1,sz) tax[i]+=tax[i-1];
for(i=len;i>=1;--i) sa[tax[rnk[tp[i]]]--]=tp[i];
}
inline bool cmp(int x,int y,int w){ return tp[x]==tp[y]&&tp[x+w]==tp[y+w]; }
void SufSort(){
int i,x;
rep(i,1,len) rnk[i]=name[i],tp[i]=i;
Qsort();
for(x=1;x<=len;x<<=1){
int num=0;
rep(i,len-x+1,len) tp[++num]=i;
rep(i,1,len) if(sa[i]>x) tp[++num]=sa[i]-x;
Qsort();memcpy(tp,rnk,sizeof(tp));
rnk[sa[1]]=1;
rep(i,2,len) rnk[sa[i]]=rnk[sa[i-1]]+(!cmp(sa[i],sa[i-1],x));
if(rnk[sa[len]]==len) return;
sz=rnk[sa[len]];
}
}
void GetHeight(){
int i,j,k=0;
memset(f,0x3f,sizeof(f));
for(i=1;i<=len;++i){
if(k) k--;
int j=sa[rnk[i]-1];
while(name[i+k]==name[j+k]) k++;
height[rnk[i]]=f[rnk[i]][0]=k;
}
for(i=1;(1<<i)<=len;++i)
for(j=1;j<=len;++j)
f[j][i]=min(f[j][i-1],f[j+(1<<(i-1))][i-1]);
}
int lcp(int x,int y){
int l=x+1,r=y,w=log2(r-l+1);
return min(f[l][w],f[r-(1<<w)+1][w]);
}
}
namespace Query{
int bl[M],t[M],tot=0,ans1[M],ans2[M],cnt=0;
struct ques{
int l,r,id;
bool operator <(const ques &a)const{ return (bl[l]==bl[a.l])?(bl[l]&1?r>a.r:r<a.r):l<a.l; }
}q[M];
int getl(int x,int y){
int l=1,r=x-1,ans=x;
while(l<=r){
int mid=l+r>>1;
if(SA::lcp(mid,x)>=y) ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
int getr(int x,int y){
int l=x+1,r=SA::len,ans=x;
while(l<=r){
int mid=l+r>>1;
if(SA::lcp(x,mid)>=y) ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
void init(){
int i,n=SA::len,block=sqrt(n);
rep(i,1,n) bl[i]=(i-1)/block+1;
rep(i,1,m){
int L=getl(SA::rnk[bg[i]],ll[i]),R=getr(SA::rnk[bg[i]],ll[i]);
if(L<=R)q[++cnt]=(ques){L,R,i};
// printf("%d : %d %d\n",i,L,R);
}
}
inline void add(int x,int y){
if(++t[id[SA::sa[x]]]==1 && id[SA::sa[x]])
tot++,ans2[id[SA::sa[x]]]+=m-y+1;
}
inline void del(int x,int y){
if(--t[id[SA::sa[x]]]==0 && id[SA::sa[x]])
tot--,ans2[id[SA::sa[x]]]-=m-y+1;
}
void solve(){
sort(q+1,q+cnt+1);
memset(t,0,sizeof(t));
int i,L=1,R=0;
rep(i,1,cnt){
while(R<q[i].r) add(++R,i);
while(L>q[i].l) add(--L,i);
while(R>q[i].r) del(R--,i);
while(L<q[i].l) del(L++,i);
ans1[q[i].id]=tot;
}
rep(i,1,m) printf("%d\n",ans1[i]);
rep(i,1,n) printf("%d ",ans2[i]);
}
}
int main(){
SA::init();
SA::SufSort();
SA::GetHeight();
Query::init();
Query::solve();
}
洛谷P2336 [SCOI2012]喵星球上的点名(后缀数组+莫队)的更多相关文章
- 洛谷 P2336 [SCOI2012]喵星球上的点名 解题报告
P2336 [SCOI2012]喵星球上的点名 题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 \(N\) 个喵星人,每个喵星人的 ...
- P2336 [SCOI2012]喵星球上的点名(SA+莫队)
题面传送门 一道还算有点含金量的 SA 罢-- 首先按照套路我们把读入的所有字符串都粘在一起,中间用分隔符隔开并建出后缀数组出来. 我们考虑对于一个固定的字符串 \(s\),什么样的字符串 \(t\) ...
- 洛咕 P2336 [SCOI2012]喵星球上的点名
洛咕 P2336 [SCOI2012]喵星球上的点名 先求出SA和height,一个点名串对应的就是一段区间,还有很多个点,就转化成了 有很多个区间,很多个点集,对每个区间计算和多少个点集有交,对每个 ...
- BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]
2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1906 Solved: 839[Submit][St ...
- Luogu2336 SCOI2012 喵星球上的点名 SA、莫队
传送门 一道很套路的题目 先将所有串拼在一起,两个不同的串之间放一个没有出现在任何串中的字符做分隔,然后SA 那么对于所有点名串能够点到的名字串在SA中对应一段区间 把这些区间拿出来然后莫队统计每一个 ...
- P2336 [SCOI2012]喵星球上的点名(后缀自动机+莫队+dfs序)
P2336 [SCOI2012]喵星球上的点名 名字怎么存?显然是后缀自动机辣 询问点到多少个喵喵喵其实就是 查询后缀自动机上parent树的一个子树 于是我们考虑莫队 怎么树上莫队呢 我们用dfs序 ...
- BZOJ 2754 SCOI 2012 喵星球上的点名 后缀数组 树状数组
2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2068 Solved: 907[Submit][St ...
- Luogu P2336 [SCOI2012]喵星球上的点名
题目链接 \(Click Here\)_ \(200\)行纯干货的代码,一发\(WA\)掉真的是让人窒息,幸好最后找到了锅在哪.(差点就要弃掉了\(QAQ\)) [调出来的时候真的是要高兴到哭出来了\ ...
- 【BZOJ2754】[SCOI2012]喵星球上的点名
[BZOJ2754][SCOI2012]喵星球上的点名 题面 bzoj 洛谷 题解 这题有各种神仙做法啊,什么暴力\(AC\)自动机.\(SAM\)等等五花八门 我这个蒟蒻在这里提供一种复杂度正确且常 ...
随机推荐
- 使用 maven 创建 java web 工程
本文主要讲述使用 maven 命令行的形式来创建 java web 工程 开发环境 jdk 1.7 maven 3.5.0 spring 3.2 tomcat 7 eclipse Mars Rele ...
- SyntaxError: expected expression, got '<'
用firebug查看网络请求发现js没有问题,问题在于ajax返回的数据错误,格式是<script type='text/javascript'> ... ... </script& ...
- CSS实现文字两端对齐
最近的项目遇到了这样的需求:(要求标题部分不管文字多少,都必须两端对齐) 如下图: 当时也没有多想直接使用‘ ’进行代替,毕竟产品同学想快一点看到效果,不敢怠慢!不过到第二个页面就傻眼了. 如图: 这 ...
- select实现三级联动
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- CF17E Palisection
题意 给定一个长度为n的小写字母串.问你有多少对相交的回文子串(包含也算相交) 相交的回文子串个数 \(mod\ 51123987\) Sol 求相交的回文子串不太好求 考虑用总数减去不相交的回文串个 ...
- sublime3下载安装及常用插件、浏览器预览设置
之前与学习前端有关的软件都安装在了实验室电脑上,最近由于要放寒假(也许我寒假回去会学习呢),于是得在笔记本电脑上重新安装一遍.几个软件各种出错,花了一下午才安装好,必须记录下来啊! 这篇文章主要介绍s ...
- WeinView 与 MITSUBISHI FX 系列 PLC 通讯范例
1. 范例操作概述 此范例将介绍如何快捷简易地建立WEINVIEW HMI与MITSUBISHI FX系列 PLC通讯. 注意事项:通讯参数设置,通讯线接法. 2. 规划说明 (1) 新建简单 PLC ...
- 实验吧Crypto题目Writeup
这大概是一篇不怎么更新的没什么用的网上已经有了很多差不多的东西的博客. 变异凯撒 忘记了2333 传统知识+古典密码 先查百度百科,把年份变成数字,然后猜测+甲子的意思,一开始以为是加1,后来意识到是 ...
- MySQL order null 0 - 把null和0(零)排在最后
1.一般的order by 语句其返回的结果为 SELECT `vcenter_ip`, `status`, `sla_id` FROM vm_list ORDER BY sla_id ASC; 2. ...
- PRINCE2的优势有哪些?
PRINCE2之所以迅速发展的原因之一是许多企业认识到建立适合自己企业的项目管理标准是一项耗时耗财的工作. 他们至少要花费6-12个月.成千上万个工时来建立一套方法,而这只是最初的成本. 之后他们必须 ...