山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

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

 

【题目链接】

 

  http://www.lydsy.com/JudgeOnline/problem.php?id=2754

 

【题意】

 

  每只喵有名姓,如果被老师点到名或姓的子串都要答道,但每只喵一次点名只答一次,问每次有多少只喵答道,以及每只喵答道多少次。

 

【思路】

 

       后缀数组

       将所有的串连起来,包括姓名和询问。处理出rank[],sa[],height[],通过rank确定一个询问的位置,然后在height上左右各扫一下,统计即可。flag对同一只标记,kase是时间戳(也算知道叫什么了=-=)

 

【代码】

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int N = 3*1e5+1e2;
  8 
  9 int s[N];
 10 int sa[N],height[N],rank[N],t[N],t2[N],c[N];
 11 
 12 void build_sa(int m,int n) {
 13     int i,k,*x=t,*y=t2;
 14     for(i=0;i<m;i++) c[i]=0;
 15     for(i=0;i<n;i++) c[x[i]=s[i]]++;
 16     for(i=0;i<m;i++) c[i]+=c[i-1];
 17     for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
 18     for(k=1;k<=n;k<<=1) {
 19         int p=0;
 20         for(i=n-k;i<n;i++) y[p++]=i;
 21         for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
 22         for(i=0;i<m;i++) c[i]=0;
 23         for(i=0;i<n;i++) c[x[y[i]]]++;
 24         for(i=0;i<m;i++) c[i]+=c[i-1];
 25         for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
 26         swap(x,y);
 27         p=1; x[sa[0]]=0;
 28         for(i=1;i<n;i++) 
 29             x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]? p-1:p++;
 30         if(p>=n) break;
 31         m=p;
 32     }
 33 }
 34 void get_height(int n) {
 35     int i,j,k=0;
 36     for(i=0;i<n;i++) rank[sa[i]]=i;
 37     for(i=0;i<n;i++) {
 38         if(k) k--;
 39         j=sa[rank[i]-1];
 40         while(s[i+k]==s[j+k]) k++;
 41         height[rank[i]]=k;
 42     }
 43 }
 44 
 45 int n,m;
 46 int flag[N],kase,ans[N],from[N],que[N],length[N];
 47 void read(int& x) {
 48     char c=getchar(); int f=1; x=0;
 49     while(!isdigit(c)){if(c=='-')f=-1; c=getchar();}
 50     while(isdigit(c)) x=x*10+c-'0',c=getchar();
 51     x*=f;
 52 }
 53 int main() {
 54     memset(from,-1,sizeof(from));
 55     read(n),read(m);
 56     int x,len=0;
 57     for(int i=0;i<n;i++) {
 58         read(x);
 59         for(int j=0;j<x;j++)
 60             read(s[len]),from[len++]=i;
 61         s[len++]=10001;
 62         read(x);
 63         for(int j=0;j<x;j++)
 64             read(s[len]),from[len++]=i;
 65         s[len++]=10001;
 66     }
 67     for(int i=0;i<m;i++) {
 68         read(x);
 69         que[i]=len; length[i]=x;
 70         for(int j=0;j<x;j++)
 71             read(s[len++]);
 72         s[len++]=10001;
 73     }
 74     build_sa(10002,len);
 75     get_height(len);
 76     for(int i=0;i<m;i++) {
 77         int p=rank[que[i]],tot=0;
 78         ++kase;
 79         while(height[p]>=length[i]) {
 80             if(from[sa[p-1]]!=-1)
 81                 if(flag[from[sa[p-1]]]!=kase) {
 82                     flag[from[sa[p-1]]]=kase;
 83                     ++tot;
 84                     ++ans[from[sa[p-1]]];
 85                 }
 86             p--;
 87             if(!p) break;
 88         }
 89         p=rank[que[i]];
 90         while(height[p+1]>=length[i]) {
 91             if(from[sa[p+1]]!=-1)
 92                 if(flag[from[sa[p+1]]]!=kase) {
 93                     flag[from[sa[p+1]]]=kase;
 94                     ++tot;
 95                     ++ans[from[sa[p+1]]];
 96                 }
 97             p++;
 98             if(p==len) break;
 99         }
100         printf("%d\n",tot);
101     }
102     printf("%d",ans[0]);
103     for(int i=1;i<n;i++) printf(" %d",ans[i]);
104 }

 

posted on 2016-02-20 12:46  hahalidaxin  阅读(380)  评论(0编辑  收藏  举报