http://www.elijahqi.win/archives/615
题目描述

a180285 幸运地被选做了地球到喵星球的留学生。他发现喵星人在上课前的点名现象非常有趣。

假设课堂上有 N 个喵星人,每个喵星人的名字由姓和名构成。喵星球上的老师会选择M 个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这个喵星人就必须答到。

然而,由于喵星人的字码过于古怪,以至于不能用 ASCII 码来表示。为了方便描述,a180285 决定用数串来表示喵星人的名字。

现在你能帮助 a180285 统计每次点名的时候有多少喵星人答到,以及 M 次点名结束后每个喵星人答到多少次吗?

输入输出格式

输入格式:

现在定义喵星球上的字符串给定方法:

先给出一个正整数 L ,表示字符串的长度,接下来L个整数表示字符串的每个字符。

输入的第一行是两个整数 N 和 M。

接下来有 N 行, 每行包含第 i 个喵星人的姓和名两个串。 姓和名都是标准的喵星球上的字符串。

接下来有 M 行,每行包含一个喵星球上的字符串,表示老师点名的串。

输出格式:

对于每个老师点名的串输出有多少个喵星人应该答到。

然后在最后一行输出每个喵星人被点到多少次。

输入输出样例

输入样例#1:

2 3
6 8 25 0 24 14 8 6 18 0 10 20 24 0
7 14 17 8 7 0 17 0 5 8 25 0 24 0
4 8 25 0 24
4 7 0 17 0
4 17 0 8 25
输出样例#1:

2
1
0
1 2
说明

事实上样例给出的数据如果翻译成地球上的语言可以这样来看

2 3 izayoi sakuya

orihara izaya

izay hara raiz

对于 30%的数据,保证:

1<=N,M<=1000,喵星人的名字总长不超过 4000,点名串的总长不超过 2000,

对于 100%的数据,保证:

1<=N<=20000 ,1<=M<=50000. 喵星人的名字总长和点名串的总长分别不超过100000,保证喵星人的字符串中作为字符存在的数不超过 10000

有了之前的经历,二分的速度似乎还不如暴力搞搞速度快呢

这里相比上一个tjoi2013需要限制一下不要查到问询的字符串里去 并且假如是属于同一块那么tmp记录的答案只统计一次


#include<cstdio>
#include<cstring>
#define N 2020010
inline int read(){int x=0;char ch=getchar();while (ch<'0'||ch>'9') ch=getchar();while (ch<='9'&&ch>='0') {x=x*10+ch-'0';ch=getchar();}return x;
}
int n,m,a[N],n1,m1,bl[N],count[N],rank[N<<1],rank1[N],sa[N],height[N],k,tmp[N],visit[N],ans[N];
struct node{int st,len;
}data[55000];
int main(){
//    freopen("2336.in","r",stdin);n1=read();m1=read();n=1;m=10000;for (int i=1;i<=n1;++i){int tmp=read();for (int j=0;j<tmp;++j) a[n+j]=read(),bl[n+j]=i;n+=tmp;a[n++]=++m;tmp=read();for (int j=0;j<tmp;++j) a[n+j]=read(),bl[n+j]=i;n+=tmp;a[n++]=++m;}int last=n-1;for (int i=1;i<=m1;++i){int tmp=read();data[i].st=n;data[i].len=tmp;for (int j=0;j<tmp;++j) a[n+j]=read();n+=tmp;a[n++]=++m;}n-=1;
//    printf("%d\n",n);//for (int i=1;i<=n;++i) printf("%d\n",a[i]);for (int i=1;i<=n;++i) count[a[i]]=1;for (int i=1;i<=m;++i) count[i]+=count[i-1];for (int i=1;i<=n;++i) rank[i]=count[a[i]];k=0;count[0]=0;for (int p=1;k!=n;p<<=1,m=k){for (int i=1;i<=m;++i) count[i]=0;for (int i=1;i<=n;++i) count[rank[i+p]]++;for (int i=1;i<=m;++i) count[i]+=count[i-1];for (int i=n;i>=1;--i) tmp[count[rank[i+p]]--]=i;for (int i=1;i<=m;++i) count[i]=0;for (int i=1;i<=n;++i) count[rank[i]]++;for (int i=1;i<=m;++i) count[i]+=count[i-1];for (int i=n;i>=1;--i) sa[count[rank[tmp[i]]]--]=tmp[i];memcpy(rank1,rank,sizeof(rank)>>1);rank[sa[1]]=k=1;for (int i=2;i<=n;++i){if (rank1[sa[i]]!=rank1[sa[i-1]]||rank1[sa[i]+p]!=rank1[sa[i-1]+p]) ++k;rank[sa[i]]=k;}}k=0;for (int i=1;i<=n;++i){if (rank[i]==1) continue;k=k==0?0:k-1;while (a[i+k]==a[sa[rank[i]-1]+k]) ++k;height[rank[i]]=k;}
//    for (int i=1;i<=n;++i) printf("%d ",sa[i]);printf("\n");
//    for (int i=1;i<=n;++i) printf("%d ",height[i]);for (int i=1;i<=m1;++i){int l=rank[data[i].st],r=rank[data[i].st]+1;while (height[l]>=data[i].len) --l;while (height[r]>=data[i].len) ++r;--r;int tmp=0;for (int j=l;j<=r;++j){if (sa[j]>last) continue;//超过了答案寻找的范围if (visit[bl[sa[j]]]==i) continue; tmp++;ans[bl[sa[j]]]++;visit[bl[sa[j]]]=i;}printf("%d\n",tmp);}for (int i=1;i<=n1;++i) printf("%d ",ans[i]);return 0;
}

二分查找x

#include<cstdio>
#include<cstring>
#define N 2020010
inline int read(){int x=0;char ch=getchar();while (ch<'0'||ch>'9') ch=getchar();while (ch<='9'&&ch>='0') {x=x*10+ch-'0';ch=getchar();}return x;
}
int n,m,a[N],n1,m1,bl[N],count[N],rank[N<<1],rank1[N],sa[N],height[N],k,tmp[N],visit[N],ans[N],l,r,fmin[N][20],Log[N];
struct node{int st,len;
}data[55000];
inline int min(int x,int y){return x<y?x:y;}
inline int lcp(int x,int y){x++;int t=Log[y-x+1];return min(fmin[x][t],fmin[y-(1<<t)+1][t]);
}
void check(int st,int len){int l1,r1;if (height[st]<len) l1=st;else{int ll=1,rr=st-1;while (ll<=rr){int mid=(ll+rr)>>1;if(lcp(mid,st)>=len) rr=mid-1;else ll=mid+1;}l1=ll;}if (height[st+1]<len) r1=st;else{int ll=st+1,rr=n;while (ll<=rr){int mid=(ll+rr)>>1;if (lcp(st,mid)>=len) ll=mid+1;else rr=mid-1;}r1=rr;}l=l1;r=r1;
}
int main(){freopen("2336.in","r",stdin);n1=read();m1=read();n=1;m=10000;for (int i=1;i<=n1;++i){int tmp=read();for (int j=0;j<tmp;++j) a[n+j]=read(),bl[n+j]=i;n+=tmp;a[n++]=++m;tmp=read();for (int j=0;j<tmp;++j) a[n+j]=read(),bl[n+j]=i;n+=tmp;a[n++]=++m;}int last=n-1;for (int i=1;i<=m1;++i){int tmp=read();data[i].st=n;data[i].len=tmp;for (int j=0;j<tmp;++j) a[n+j]=read();n+=tmp;a[n++]=++m;}n-=1;
//  printf("%d\n",n);//for (int i=1;i<=n;++i) printf("%d\n",a[i]);for (int i=1;i<=n;++i) count[a[i]]=1;for (int i=1;i<=m;++i) count[i]+=count[i-1];for (int i=1;i<=n;++i) rank[i]=count[a[i]];k=0;count[0]=0;for (int p=1;k!=n;p<<=1,m=k){for (int i=1;i<=m;++i) count[i]=0;for (int i=1;i<=n;++i) count[rank[i+p]]++;for (int i=1;i<=m;++i) count[i]+=count[i-1];for (int i=n;i>=1;--i) tmp[count[rank[i+p]]--]=i;for (int i=1;i<=m;++i) count[i]=0;for (int i=1;i<=n;++i) count[rank[i]]++;for (int i=1;i<=m;++i) count[i]+=count[i-1];for (int i=n;i>=1;--i) sa[count[rank[tmp[i]]]--]=tmp[i];memcpy(rank1,rank,sizeof(rank)>>1);rank[sa[1]]=k=1;for (int i=2;i<=n;++i){if (rank1[sa[i]]!=rank1[sa[i-1]]||rank1[sa[i]+p]!=rank1[sa[i-1]+p]) ++k;rank[sa[i]]=k;}}k=0;Log[0]=-1;for (int i=1;i<=n;++i) Log[i]=Log[i>>1]+1;for (int i=1;i<=n;++i){if (rank[i]==1) continue;k=k==0?0:k-1;while (a[i+k]==a[sa[rank[i]-1]+k]) ++k;height[rank[i]]=k;}for (int i=1;i<=n;++i) fmin[i][0]=height[i];for (int j=1;j<=Log[n];++j){for (int i=1;i<=n-(1<<j)+1;++i){fmin[i][j]=min(fmin[i][j-1],fmin[i+(1<<(j-1))][j-1]);}}
//  for (int i=1;i<=n;++i) printf("%d ",sa[i]);printf("\n");
//  for (int i=1;i<=n;++i) printf("%d ",height[i]);for (int i=1;i<=m1;++i){check(rank[data[i].st],data[i].len);int tmp=0;for (int j=l;j<=r;++j){if (sa[j]>last) continue;//超过了答案寻找的范围if (visit[bl[sa[j]]]==i) continue; tmp++;ans[bl[sa[j]]]++;visit[bl[sa[j]]]=i;}printf("%d\n",tmp);}for (int i=1;i<=n1;++i) printf("%d ",ans[i]);return 0;
}

bzoj2754 scoi2012 喵星球的点名相关推荐

  1. BZOJ2754: [SCOI2012]喵星球上的点名(AC自动机/后缀自动机)

    Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串 ...

  2. [BZOJ2754][SCOI2012]喵星球上的点名(后缀数组+莫队)

    Address 洛谷P2336 BZOJ2754 LOJ#2374 Solution 考虑在每个人的姓和名之间插入一个无关的字符. 这样问题就转化成了一些主串和一些模式串,询问每个模式串能匹配到多少个 ...

  3. [BZOJ2754]-[SCOI2012]喵星球上的点名-AC自动机+树状数组

    说在前面 感觉这题还是挺经典的 所以还是写了记录一下- 题目 BZOJ2754传送门 洛谷P2336传送门 看题可进传送门 题目-略长,概括起来有点麻烦 解法 读完这道题之后,可以发现实际上它就是要我 ...

  4. bzoj2754: [SCOI2012]喵星球上的点名

    传送门 事实证明,我肉眼debug了两个晚上,还是不及对拍效率高. AC自动机写错了都毫不自觉的智障宸 因为数据水,写的暴力 //Achen #include<algorithm> #in ...

  5. [BZOJ2754][SCOI2012]喵星球上的点名 后缀数组

    不科学啊...这题暴力可过...感觉所有串都是a就可以卡掉啊... 我的做法就是先把姓名串和询问串全部连在一起,并打上分隔符,并记录每个字符属于哪个串,求出SA.对于每个询问就从它所在的位置左右扫he ...

  6. 洛谷2336 BZOJ2754 SCOI2012 喵星球上的点名 SA 莫队 二分

    题目链接 题意: 有nnn个人,每个人有两个串,一个表示姓,一个表示名,这里用数字表示字符.有mmm次询问,对于每次询问,你要回答有多少个人的姓或者名至少有一个是给出的串的子串.最后再对于这nnn个人 ...

  7. 【BZOJ2754】[SCOI2012]喵星球上的点名

    [BZOJ2754][SCOI2012]喵星球上的点名 题面 bzoj 洛谷 题解 这题有各种神仙做法啊,什么暴力\(AC\)自动机.\(SAM\)等等五花八门 我这个蒟蒻在这里提供一种复杂度正确且常 ...

  8. BZOJ 2754: [SCOI2012]喵星球上的点名

    二次联通门 : BZOJ 2754: [SCOI2012]喵星球上的点名 /*BZOJ 2754: [SCOI2012]喵星球上的点名此题有N种做法...见到众dalao用各种奇怪的姿势AC此题..具 ...

  9. 洛谷 P2336 [SCOI2012]喵星球上的点名 解题报告

    P2336 [SCOI2012]喵星球上的点名 题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 \(N\) 个喵星人,每个喵星人的 ...

最新文章

  1. GlideApp 引入不了问题
  2. MongoDB 索引
  3. android与mysql数据库同步_android开发 如何通过web服务器访问MYSQL数据库并且使其数据同步到android SQLite数据库?...
  4. 4024-砾石的交换排序(C++,附思路)
  5. Lync 2010迁移Lync 2013 PART5:支持旧版Lync
  6. 如何用AltiumDesigner绘制STC89C51单片机原理图
  7. 如何恢复误删SD卡文件?SD卡误删除数据恢复
  8. C# CS客户端不显示垂直滚动条
  9. Excel打开CSV文件,数字起始0丢失问题
  10. 示例代码-协方差,黎曼协方差计算.
  11. Northleaf扩大业务开发团队,任命Chris O’Connor 为澳大利亚和新西兰地区董事总经理
  12. RocketMQ学习笔记:基础知识和安装启动
  13. 深度学习基础(九)—— 稀疏编码(sparse coding)
  14. matlab 工业相机 曝光时间_工业相机的曝光、曝光时间、快门、增益
  15. html页面无法显示生僻字,生僻字打不出来怎么办
  16. 彻底明白php中cgi、fastcgi和php-cgi、php-fpm及php运行原理
  17. CGI实现文件的上传和下载
  18. [享学Eureka] 一、源生Eureka介绍 --- 基于注册中心的服务发现
  19. 【神DP】-ZOJ-3623-Battle Ships
  20. 就该这么学llinux 第五章用户身份与文件权限

热门文章

  1. SAP部署SSL数字证书
  2. unity android输入法,Unity打包Android 输入法弹出界面上移的问题
  3. 深圳关内主要旅游景点地址和公交路线
  4. SparseArray与ArrayMap
  5. sudo dolphin_如何使用Dolphin在PC上玩Wii和GameCube游戏
  6. RK3588S Android12 旋转系统图像
  7. 戒指的带法,终于收齐了
  8. html5 css js前端开发五子棋UI篇--基于慕课网五子棋视频教程的随笔
  9. 精诚所至,金石为开!
  10. u8 u16 u32 u64 c++