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

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。

 
 
和3172有点类似,也是用AC自动机建立fail树然后在fail树上统计答案。。。
  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<algorithm>
  7 #include<string>
  8 #include<map>
  9 #include<queue>
 10 #include<vector>
 11 #include<set>
 12 #define inf 1000000000
 13 #define maxn 100000+5
 14 #define maxm 50000+5
 15 #define eps 1e-10
 16 #define ll long long
 17 #define for0(i,n) for(int i=0;i<(n);i++)
 18 #define for1(i,n) for(int i=1;i<=(n);i++)
 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
 22 using namespace std;
 23 int read(){
 24     int x=0,f=1;char ch=getchar();
 25     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 26     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 27     return x*f;
 28 }
 29 int n,m,ans1[maxn],ans2[maxn];
 30 vector<int> a[20005],st[maxn],V,M;
 31 map<int,int> next[maxn];
 32 bool v[maxn],mark[maxm];
 33 struct acm{
 34     int tot,ans;
 35     int fail[maxn],q[maxn];
 36     acm(){
 37         tot=1;
 38         for(int i=-1;i<=10000;i++)
 39             next[0][i]=1;
 40         fail[1]=0;
 41     }
 42     void insert(int pos){
 43         int now=1,L=read();
 44         for1(i,L){
 45             int x=read();
 46             if(!next[now][x])next[now][x]=++tot;
 47             now=next[now][x];
 48         }
 49         st[now].push_back(pos); 
 50     }
 51     void build(){
 52         int head=0,tail=1;
 53         q[0]=1;
 54         while(head!=tail){
 55             int now=q[head];head++;
 56             for(map<int,int>::iterator i=next[now].begin();i!=next[now].end();i++){
 57                 int t=i->first,k=fail[now];
 58                 while(!next[k][t])k=fail[k];
 59                 fail[i->second]=next[k][t];
 60                 q[tail++]=i->second;
 61             }
 62         }
 63     }
 64     void get(int pos,int x){
 65         for(int i=x;i;i=fail[i])
 66             if(!v[i]){
 67                 v[i]=1;V.push_back(i);
 68                 for(int j=0;j<st[i].size();j++)
 69                     if(!mark[st[i][j]]){
 70                         mark[st[i][j]]=1;M.push_back(st[i][j]);
 71                         ans1[st[i][j]]++;
 72                         ans2[pos]++;
 73                     }
 74             }
 75             else break;
 76     }
 77     void solve(int x){
 78         int now=1;
 79         for0(i,a[x].size()){
 80             int t=a[x][i];
 81             while(!next[now][t])now=fail[now];
 82             now=next[now][t];get(x,now);
 83         }
 84         for0(i,V.size())v[V[i]]=0;
 85         for0(i,M.size())mark[M[i]]=0;
 86         V.clear();M.clear();
 87     }
 88 }acm;
 89 int main(){
 90     //freopen("input.txt","r",stdin);
 91     //freopen("output.txt","w",stdout);
 92     n=read();m=read();
 93     int L,x;
 94     for1(i,n){
 95         L=read(),x;
 96         while(L--)x=read(),a[i].push_back(x);
 97         a[i].push_back(-1);
 98         L=read();
 99         while(L--)x=read(),a[i].push_back(x);
100     }
101     for1(i,m)
102         acm.insert(i);
103     acm.build();
104     for1(i,n)
105         acm.solve(i);
106     for1(i,m)printf("%d\n",ans1[i]);
107     for1(i,n){
108         printf("%d",ans2[i]);
109         if(i!=n)printf(" ");
110     }
111     return 0;
112 }
View Code

 

posted @ 2016-06-02 09:51  HTWX  阅读(153)  评论(0编辑  收藏  举报