BYRBT

SCOI 2012 喵星球上的点名

题目:http://61.187.179.132/JudgeOnline/problem.php?id=2754

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。

 

题解:

  题意简化后就是询问m个串在另外n个串中个出现了多少次。

 

  于是就是经典的字符串匹配模型了。

 

  用后缀数组MS可以搞,但是我不会。

 

  于是就用AC自动机了,把m个串建成自动机,然后一个一个地把n个串带进去询问就行了,跟裸的自动机没多大区别。

 

  考试的时候打掉了一行话,果断就悲剧掉了…………………………

 

  题其实不难,能否1A才是关键。

 

View Code
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<map>
  5 #include<queue>
  6  
  7 using namespace std;
  8  
  9 const int maxl=100001;
 10 const int maxn=20001;
 11 const int maxm=50001;
 12  
 13 int q[maxm],nownum[maxl],next[maxm],ll,check[maxm],v[maxl],answer[maxn],ask[maxm],n,m,l;
 14  
 15 struct person
 16 {
 17     int p1,l1,l2,p2;
 18 }pe[maxn];
 19  
 20 struct node
 21 {
 22     int ans_f;
 23     map < int , node * > next;
 24     node *fail;
 25     node()
 26     {
 27         fail=0;
 28         ans_f=0;
 29     }
 30 };
 31  
 32 queue<node *> que;
 33  
 34 void insert(node *root,int *nownum,int now)
 35 {
 36     int l=0;
 37     node *p=root;
 38     while (nownum[l]!=-1)
 39     {
 40         if (p->next[nownum[l]]==NULL) p->next[nownum[l]]=new node;
 41         p=p->next[nownum[l]];
 42         l++;
 43     }
 44     ll++;
 45     q[ll]=now;
 46     next[ll]=p->ans_f;
 47     p->ans_f=ll;
 48 }
 49  
 50 void build_AC(node *root)
 51 {
 52     que.push(root);
 53     root->fail=NULL;
 54     while (que.size())
 55     {
 56         node *p=que.front();
 57         que.pop();
 58         for (map < int , node * >::iterator crf=p->next.begin();crf!=p->next.end();crf++)
 59             if (crf->second!=NULL)
 60             {
 61                 node *ljl=crf -> second;
 62                 int v= crf -> first;
 63                 node *last=p->fail;
 64                 while (last!=NULL)
 65                 {
 66                     if (last->next[v]!=NULL)
 67                     {
 68                         ljl->fail=last->next[v];
 69                         break;
 70                     }
 71                     last=last->fail;
 72                 }
 73                 if (last==NULL) ljl->fail=root;
 74                 int nowp=ljl->ans_f,lastp=0;
 75                 while (nowp!=0)
 76                 {
 77                     lastp=nowp;
 78                     nowp=next[nowp];
 79                 }
 80                 if (lastp==0) ljl->ans_f=ljl->fail->ans_f;
 81                 else next[lastp]=ljl->fail->ans_f;
 82                 que.push(ljl);
 83             }
 84     }
 85 }
 86  
 87 void query(node *root,int now)
 88 {
 89     int l=pe[now].p1;
 90     node *p=root;
 91     while (l<=pe[now].p1+pe[now].l1-1)
 92     {
 93         while (p!=root && p->next[v[l]]==NULL)
 94             p=p->fail;
 95         p=p->next[v[l]];
 96         if (p==NULL) p=root;
 97         else
 98         {
 99             int nowp=p->ans_f;
100             while (nowp!=0)
101             {
102                 if (check[q[nowp]]!=now)
103                 {
104                     check[q[nowp]]=now;
105                     answer[now]++;
106                     ask[q[nowp]]++;
107                 }
108                 nowp=next[nowp];
109             }
110         }
111         l++;
112     }
113     l=pe[now].p2;
114     p=root;
115     while (l<=pe[now].p2+pe[now].l2-1)
116     {
117         while (p!=root && p->next[v[l]]==NULL)
118             p=p->fail;
119         p=p->next[v[l]];
120         if (p==NULL) p=root;
121         else
122         {
123             int nowp=p->ans_f;
124             while (nowp!=0)
125             {
126                 if (check[q[nowp]]!=now)
127                 {
128                     check[q[nowp]]=now;
129                     answer[now]++;
130                     ask[q[nowp]]++;
131                 }
132                 nowp=next[nowp];
133             }
134         }
135         l++;
136     }
137 }
138  
139 int main()
140 {
141     //freopen("name.in","r",stdin);
142     //freopen("name.out","w",stdout);
143  
144     scanf("%d%d",&n,&m);
145     l=-1;
146     for (int a=1;a<=n;a++)
147     {
148         scanf("%d",&pe[a].l1);
149         pe[a].p1=l+1;
150         for (int b=1;b<=pe[a].l1;b++)
151         {
152             l++;
153             scanf("%d",&v[l]);
154         }
155         scanf("%d",&pe[a].l2);
156         pe[a].p2=l+1;
157         for (int b=1;b<=pe[a].l2;b++)
158         {
159             l++;
160             scanf("%d",&v[l]);
161         }
162     }
163     node *root=new node;
164     for (int a=1;a<=m;a++)
165     {
166         int nowl;
167         scanf("%d",&nowl);
168         for (int b=0;b<nowl;b++)
169             scanf("%d",&nownum[b]);
170         nownum[nowl]=-1;
171         insert(root,nownum,a);
172     }
173     build_AC(root);
174     for (int a=1;a<=n;a++)
175         query(root,a);
176     for (int a=1;a<=m;a++)
177         printf("%d\n",ask[a]);
178     for (int a=1;a<=n;a++)
179     {
180         printf("%d",answer[a]);
181         if (a==n) printf("\n");
182         else printf(" ");
183     }
184  
185     return 0;
186 }

 

posted @ 2012-04-30 13:56  zhonghaoxi  阅读(864)  评论(4编辑  收藏  举报
BYRBT