码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-07-06 17:29:40      阅读:265      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   数据   

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\n",query_gets[i]);
        }
        for (i=0;i<n-1;i++)
        {
                printf("%d ",cat_gets[i]);
        }
        printf("%d\n",cat_gets[n-1]);
}
int main()
{
        init();
        work();
        return 0;
}

 

BZOJ 2754: [SCOI2012]喵星球上的点名,布布扣,bubuko.com

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

标签:des   style   blog   http   color   数据   

原文地址:http://www.cnblogs.com/mhy12345/p/3825140.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!