• 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 }
  • 相关阅读:
    Grub 和 UEFI启动
    神舟战神插上耳机没有声音,重启又有声音..
    批处理 ------ @、ECHO OFF、ECHO ON 的使用
    linux command ------ find
    Adobe Premiere Pro CC ------ 快捷键
    分布式session一致性问题
    DNS域名解析
    CDN内容分发
    令牌桶限流算法和漏桶限流算法区别
    AOP与IOC区别
  • 原文地址:https://www.cnblogs.com/zhonghaoxi/p/2476896.html
Copyright © 2020-2023  润新知