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) 编辑 收藏 举报