2754: [SCOI2012]喵喵叫的星球

Time Limit: 20 Sec  Memory Limit: 128 MB

Submit: 805  Solved: 380

[

id=2754" style="color:blue; text-decoration:none">Submit][Status][Discuss]

Description

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

如果课堂上有N个喵星人,每一个喵星人的名字由姓和名构成。喵星球上的老师会选择M个串来点名。每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这个喵星人就必须答到。 然而,因为喵星人的字码过于古怪,以至于不能用ASCII码来表示。为了方便描写叙述,a180285决定用数串来表示喵星人的名字。

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

Input

 
如今定义喵星球上的字符串给定方法:
先给出一个正整数L,表示字符串的长度,接下来L个整数表示字符串的每一个字符。
输入的第一行是两个整数N和M。
接下来有N行。每行包括第i 个喵星人的姓和名两个串。姓和名都是标准的喵星球上的
字符串。
接下来有M行,每行包括一个喵星球上的字符串,表示老师点名的串。

Output

 
对于每一个老师点名的串输出有多少个喵星人应该答到。
然后在最后一行输出每一个喵星人被点到多少次。

Sample Input

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

Sample Output



2

1

0

1 2

【提示】

其实例子给出的数据假设翻译成地球上的语言能够这样来看

2 3

izayoi sakuya

orihara izaya

izay

hara

raiz

HINT

【数据范围】 



 对于30%的数据,保证: 



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

对于100%的数据,保证:



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

Source

这题是后缀数组。

先把模式串P写成s11*s12*s21*s22...sn2 (*为特殊字符)

然后用find统计sa中出现上下界 平均O(Len总logLen总+MlogLen总) 最坏O(MLen总)

可能会T但正解至今仍不知道

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (1000000+10)
#define Sigma_size (10000+10)
#define sp_char (10001)
typedef long long ll;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
// 约定 -1:/0 sp_char:* cat[i]=0 该位置无猫
class SA
{
public:
int s[MAXN];
int sa[MAXN],t[MAXN],t2[MAXN],c[MAXN],n;
SA(){}
SA(int *_s,int _n){memcpy(s,_s,sizeof(s));n=_n;MEM(sa) MEM(t) MEM(t2) MEM(c) }
void mem(int *_s,int _n){memcpy(s,_s,sizeof(s));n=_n;MEM(sa) MEM(t) MEM(t2) MEM(c) }
void build_sa(int m)
{
int *x=t,*y=t2;
Rep(i,m) c[i]=0;
Rep(i,n) c[x[i]=s[i]]++; //x[i] 第i个字符串第一keyword排第几
For(i,m-1) c[i]+=c[i-1];
RepD(i,n-1) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1)
{
int p=0;
Fork(i,n-k,n-1) y[p++]=i;
Rep(i,n) if (sa[i]>=k) y[p++]=sa[i]-k; //y[i] 第二keyword排i的是第?字符串 Rep(i,m) c[i]=0;
Rep(i,n) c[x[y[i]]]++; // x[y[i]] 第二keyword排i的字符串,第1keyword排第几
For(i,m-1) c[i]+=c[i-1];
RepD(i,n-1) sa[--c[x[y[i]]]]=y[i]; //第二keyword从大到小遍历。以第一keyword排序 ,最后得到以1,2keyword排序的
//此时sa为第一keyword。第2keyword均排好序的
swap(x,y); //此时y变为第一keyword排序的rank,目标是把x变成第一,二keyword排序的rank
p=1; x[sa[0]]=0;
For(i,n-1)
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i]+k]==y[sa[i-1]+k] ? p-1:p++;
if (p>=n) break;
m=p;
}
}
int m; //模板串P的长度要事先赋值
int cmp_suffix(int *pattern,int p)
{
for(int i=0;i<m;i++)
{
if (pattern[i]!=s[sa[p]+i]) return pattern[i]-s[sa[p]+i];
}
return 0;
} int find(int *P,int _m)
{
m=_m; //这里赋值也行
if (cmp_suffix(P,0)<0||cmp_suffix(P,n-1)>0) return -1;
int L=0,R=n-1;
while(L<=R)
{
int M=(L+R)>>1;
int res=cmp_suffix(P,M);
if (!res) return M;
else if (res<0) R=M-1;
else L=M+1;
}
return -1;
}
int rank[MAXN],height[MAXN];
void make_height()
{
int k=0;
Rep(i,n) rank[sa[i]]=i;
Rep(i,n)
{
if (rank[i]-1<0) continue;
if (k) k--;
int j=sa[rank[i]-1];
while(s[i+k]==s[j+k]) ++k;
height[rank[i]]=k;
}
}
}S;
int flag[MAXN]={0},cat[MAXN]={0},sum[MAXN]={0};
int len,s[MAXN];
int n,m;
int get_init(int &p,int i,bool is_cat)
{
int len;
scanf("%d",&len);
while(len--)
{
scanf("%d",&s[++p]);
if (is_cat) cat[p]=i;
}
return len;
}
int main()
{
// freopen("bzoj2754.in","r",stdin);
// freopen(".out","w",stdout); scanf("%d%d",&n,&m); int p=-1;
For(i,n)
{
For(j,2)
{
get_init(p,i,1);
s[++p]=sp_char;cat[p]=0;
}
}
s[++p]=-1; S.mem(s,p);
S.build_sa(Sigma_size);
S.make_height(); For(i,m)
{
p=-1;
get_init(p,i,0);
s[++p]=-1; int K=S.find(s,p);
if (K==-1)
{
cout<<"0\n";
continue;
}
int ans=0; int t=S.sa[K];
if (flag[cat[t]]^i) sum[cat[t]]++,flag[cat[t]]=i,++ans; int k=K;
while (k>0&&S.cmp_suffix(s,k-1)==0)
{
k--;
int t=S.sa[k];
if (flag[cat[t]]^i) sum[cat[t]]++,flag[cat[t]]=i,++ans;
}
k=K;
while (k<S.n&&S.cmp_suffix(s,k+1)==0)
{
k++;
int t=S.sa[k];
if (flag[cat[t]]^i) sum[cat[t]]++,flag[cat[t]]=i,++ans;
} printf("%d\n",ans); } printf("%d",sum[1]);
Fork(i,2,n) printf(" %d",sum[i]);
putchar('\n'); return 0;
}

版权声明:本文博主原创文章。博客,未经同意不得转载。

BZOJ 2754([SCOI2012]喵喵叫的星球-统计序列的后缀阵列中子序列出现次数)的更多相关文章

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

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 649  Solved: 305[Submit][Sta ...

  2. BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1906  Solved: 839[Submit][St ...

  3. BZOJ 2754: [SCOI2012]喵星球上的点名 [AC自动机+map+暴力]

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1902  Solved: 837[Submit][St ...

  4. bzoj 2754 [SCOI2012]喵星球上的点名(后缀数组)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2754 [题意] 每只喵有名姓,如果被老师点到名或姓的子串都要答道,但每只喵一次点名只答 ...

  5. BZOJ 2754 SCOI 2012 喵星球上的点名 后缀数组 树状数组

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2068  Solved: 907[Submit][St ...

  6. 【刷题】BZOJ 2754 [SCOI2012]喵星球上的点名

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

  7. BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机+map维护Trie树)

    题目大意:略 由于字符集大,要用map维护Trie树 并不能用AC自动机的Trie图优化,不然内存会炸 所以我用AC自动机暴跳fail水过的 显然根据喵星人建AC自动机是不行的,所以要根据问题建 然而 ...

  8. bzoj 2754: [SCOI2012]喵星球上的点名【AC自动机】

    洛谷90,最后一个点死活卡不过去(也可能是我写的有问题? 比较暴力的做法,把询问带着标号建立AC自动机,用map存儿子. 然后用名字串在自动机上跑,以为是名或姓的子串就行所以把名和姓中间加个特殊字符拼 ...

  9. BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机、树状数组)

    吐槽: 为啥很多人用AC自动机暴力跳都过了?复杂度真的对么? 做法一: AC自动机+树状数组 姓名的问题,中间加个特殊字符连起来即可. 肯定是对点名串建AC自动机(map存儿子),然后第一问就相当于问 ...

随机推荐

  1. windows appfabric samples

    http://www.microsoft.com/en-us/download/details.aspx?id=19603 http://msdn.microsoft.com/zh-cn/librar ...

  2. bzoj 3165: [Heoi2013]Segment 动态凸壳

    3165: [Heoi2013]Segment Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 202  Solved: 89[Submit][Stat ...

  3. sap中用函数增加断点(break point)

    如果在增强程序中,每次调试都要去程序里面设置断点很麻烦,为了解决这个问题,可以用下面的两个方法: 1: if sy-uname eq 'XXXX'      "XXX 为账号名字 break ...

  4. EMMC 简要介绍

    一直想写一篇关于EMMC的文章,但是因为之前弄了很多PPT,所以一直提不起兴趣,索性直接把之前的一个介绍EMMC的PPT贴出来给大家看看,有什么问题可以直接跟帖,我会第一时间进行解答,谢谢

  5. 【Xamarin挖墙脚系列:时刻下载最新的Mac环境下的Xamarin安装包】

    原文:[Xamarin挖墙脚系列:时刻下载最新的Mac环境下的Xamarin安装包] 打开这两个地址,就能看到最新的安装包了.... http://www.jianshu.com/p/c67c14b3 ...

  6. Navicate使用注意事项

    2.      Navicat如何连接数据库:点击连接——>输入连接名,然后如果是本机不用更改localhost,如果是别的主机,要将对方 的ip地址输入,端口号3306不变,用户名root,密 ...

  7. linux和windows双系统导致的时间日

    我的博客:www.while0.com系统中有两种时间区分,一为UTC,另一为LT(地方时)两者的区别为时区不同,UTC就是0时区的时间,而我们当地是用的北京时间要慢8小时.linux采用的UTC时间 ...

  8. sort merge join导致temp被爆菊

    SQL_ID cqsz37256v36j, child number 1 ------------------------------------- INSERT /*+append*/ INTO T ...

  9. ♫【CSS】命名颜色

    color: aqua; 每个浏览器都支持一套它能识别且能正确渲染的命名颜色.这些颜色包括: aqua 浅绿色 #00ffffblack 黑色 #000000blue 蓝色 #0000fffuchsi ...

  10. zabbix通过jmx监控tomcat

    Zabbix版本: Zabbix 3.0.2 一.服务端配置 1.安装jdk(版本1.7.0_79) 安装与配置比较简单,过程省略.执行java -version命令,出现类似界面表示成功.   2. ...