zoukankan      html  css  js  c++  java
  • BZOJ 2754: [SCOI2012]喵星球上的点名

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

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 649  Solved: 305
    [Submit][Status]

    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。

    Source

    很裸很裸的AC自动机。只不过这道题让我基本搞懂了stl map的用法。

    map.insert(pair) 插入映射关系

    map.find(x) 查询x映射的关系,返回一个迭代器,可用first,second查找

    map<int,int>::iterator it1; 迭代器

    另外AC自动机的一个小细节,让我Wa了两遍:

    fail指针如果需要指向深度为1的节点时要特判,而且对于已经确定fail指针的节点,切忌重新复制(其实就是if语句条件要严密)。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<vector>
    using namespace std;
    #define MAXT 201000
    #define MAXN MAXT
    vector<int> query[MAXN];
    int query_gets[MAXN];
    int cat_gets[MAXN];
    int qur_vis[MAXN];
    int topq=-1;
    struct aaa
    {
            int id;
            int fail;
            int qur_id;
            map<int,int> next;
            aaa()
            {
                    qur_id=id=fail=-1;
            }
    };
    int root;
    aaa tree[MAXT];
    int topt=0;
    int name[MAXN],topn=-1;
    int str[MAXN];    
    int n,m;
    
    void add_str(int * str,int qur)
    {
            int ind;
            int now=root;
            map<int,int>::iterator it1;
            while (*str!=-1)
            {
                    ind=*(str++);
                    it1=tree[now].next.find(ind);
                    if (it1==tree[now].next.end())
                    {
                            tree[now].next.insert(make_pair(ind,++topt));
                            tree[topt].id=ind;
                            now=topt;
                    }else
                    {
                            now=it1->second;
                    }
            }
            if (tree[now].qur_id==-1)
            {
                    tree[now].qur_id=++topq;
                    query[topq].push_back(qur);
            }else
            {
                    query[tree[now].qur_id].push_back(qur);
            }
    }
    int q[MAXT];
    void build_tree()
    {
            int ope=0,clo=0,now,temp,x,ind;
            map<int,int>::iterator it1,it2;
            tree[0].fail=0;
            for (it1=tree[0].next.begin();it1!=tree[0].next.end();it1++)
            {
                    now=it1->second;
                    q[++clo]=now;
                    tree[now].fail=0;
            }
            while (ope<clo)
            {
                    now=q[++ope];
                    for (it1=tree[now].next.begin();it1!=tree[now].next.end();it1++)
                    {
                            x=it1->second;
                            ind=it1->first;
                            q[++clo]=x;
                            temp=tree[now].fail;
                            while (temp!=root)
                            {
                                    it2=tree[temp].next.find(ind);
                                    if (it2!=tree[temp].next.end())
                                    {
                                            tree[x].fail=it2->second;
                                            break;
                                    }
                                    temp=tree[temp].fail;
                            }
                            it2=tree[root].next.find(ind);
                            if (tree[x].fail==-1&&it2!=tree[root].next.end())//Oh, I forgot this part again
                            {
                                    tree[x].fail=it2->second;
                            }
                            if (tree[x].fail==-1)
                            {
                                    tree[x].fail=0;
                            }
                    }
            }
    }
    
    int count_str(int *str,int cat_id)
    {
            int ret=0;
            int now=0;
            int ind,x,temp;
            int i;
            map<int,int>::iterator it1;
            while (*str!=-1)
            {
                    ind=*(str++);    
                    it1=tree[now].next.find(ind);
                    while (now!=root&&it1==tree[now].next.end())
                    {
                            now=tree[now].fail;
                            it1=tree[now].next.find(ind);
                    }
                    if (it1==tree[now].next.end())
                    {
                            now=root;
                    }else
                    {
                            now=it1->second;
                    }
                    temp=now;
                    while (temp!=root)
                    {
                            if (tree[temp].qur_id!=-1)
                            {
                                    x=tree[temp].qur_id;
                                    for (i=0;i<query[x].size();i++)
                                    {
                                            if(qur_vis[query[x][i]]!=cat_id)
                                            {
                                                    query_gets[query[x][i]]++;
                                                    ret++;
                                                    qur_vis[query[x][i]]=cat_id;
                                            }
                                    }
                            }
                            temp=tree[temp].fail;
                    }
    
            }
            return ret;
    }
    void init()
    {
            topt=0;
            tree[0].id=-1;
            root=0;
            int i,j,x,y;
            scanf("%d%d",&n,&m);
            for (i=0;i<n*2;i++)
            {
                    scanf("%d",&x);
                    name[++topn]=x;
                    for (j=0;j<x;j++)
                    {
                            scanf("%d",&y);
                            name[++topn]=y;
                    }
                    name[++topn]=-1;
            }
            for (i=0;i<m;i++)
            {
                    scanf("%d",&x);
                    for (j=0;j<x;j++)
                    {
                            scanf("%d",&y);
                            str[j]=y;
                    }
                    str[x]=-1;
                    add_str(str,i);
            }    
            build_tree();
            memset(qur_vis,-1,sizeof(qur_vis));
    }
    void work()
    {
            int i;
            int now=0;
            for (i=0;i<n*2;i++)
            {
                    now++;
                    cat_gets[i/2]+=count_str(&name[now],i/2);
                    now+=name[now-1];
                    now++;
            }
            for (i=0;i<m;i++)
            {
                    printf("%d
    ",query_gets[i]);
            }
            for (i=0;i<n-1;i++)
            {
                    printf("%d ",cat_gets[i]);
            }
            printf("%d
    ",cat_gets[n-1]);
    }
    int main()
    {
            init();
            work();
            return 0;
    }
    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    Leetcode Valid Sudoku
    Leetcode Surrounded Regions
    LeetCode Sqrt
    LeetCode POW
    LeetCode Next Permutation
    ACK-Ackermann, 阿克曼函数
    再不懂时序就 OUT 啦!,DBengine 排名第一时序数据库,阿里云数据库 InfluxDB 正式商业化!
    阿里云提供全托管 ZooKeeper
    性能压测中的SLA,你知道吗?
    第一个入驻阿里云自营心选商城,如今它已经是营收过亿的SaaS独角兽
  • 原文地址:https://www.cnblogs.com/mhy12345/p/3825140.html
Copyright © 2011-2022 走看看