a180285幸运地被选做了地球到喵星球的留学生。他发现喵星人在上课前的点名现象非常有趣。 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成。喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这个喵星人就必须答到。 然而,由于喵星人的字码过于古怪,以至于不能用ASCII码来表示。为了方便描述,a180285决定用数串来表示喵星人的名字。
现在你能帮助a180285统计每次点名的时候有多少喵星人答到,以及M次点名结束后每个喵星人答到多少次吗?
现在定义喵星球上的字符串给定方法:
先给出一个正整数L,表示字符串的长度,接下来L个整数表示字符串的每个字符。
输入的第一行是两个整数N和M。
接下来有N行,每行包含第i 个喵星人的姓和名两个串。姓和名都是标准的喵星球上的
字符串。
接下来有M行,每行包含一个喵星球上的字符串,表示老师点名的串。
【数据范围】
对于30%的数据,保证:
1<=N,M<=1000,喵星人的名字总长不超过4000,点名串的总长不超过2000。
对于100%的数据,保证:
1<=N<=20000,1<=M<=50000,喵星人的名字总长和点名串的总长分别不超过100000,保证喵星人的字符串中作为字符存在的数不超过10000。
将所有的串连起来,包括姓名和询问。处理出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 }