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

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 1902  Solved: 837
[Submit][Status][Discuss]

Description

a180285幸运地被选做了地球到喵星球的留学生。他发现喵星人在上课前的点名现象非常有趣。   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成。喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这个喵星人就必须答到。 然而,由于喵星人的字码过于古怪,以至于不能用ASCII码来表示。为了方便描述,a180285决定用数串来表示喵星人的名字。
现在你能帮助a180285统计每次点名的时候有多少喵星人答到,以及M次点名结束后每个喵星人答到多少次吗?  

Input

现在定义喵星球上的字符串给定方法:
先给出一个正整数L,表示字符串的长度,接下来L个整数表示字符串的每个字符。
输入的第一行是两个整数N和M。
接下来有N行,每行包含第i 个喵星人的姓和名两个串。姓和名都是标准的喵星球上的
字符串。
接下来有M行,每行包含一个喵星球上的字符串,表示老师点名的串。

Output

对于每个老师点名的串输出有多少个喵星人应该答到。
然后在最后一行输出每个喵星人被点到多少次。

HINT

【数据范围】

对于30%的数据,保证:

1<=N,M<=1000,喵星人的名字总长不超过4000,点名串的总长不超过2000。

对于100%的数据,保证:

1<=N<=20000,1<=M<=50000,喵星人的名字总长和点名串的总长分别不超过100000,保证喵星人的字符串中作为字符存在的数不超过10000。


喵~ http://www.cnblogs.com/candy99/p/cat.html


首先想到两问建两个AC自动机,第一问是把喵名建自动机然后点名串统计fail子树,但是不对啊啊啊啊啊人家一个喵就算一次.....

所以就发现其他人用了个很暴力的方法,点名串建AC自动机然后喵在上面跑,每跑一个字符暴力统计更新fail指向的点名串......然后就过了

一些细节:

1.要用map  字符集太大(离散化并没有用) 这样建AC自动机的时候就不能用Trie图优化了用普通做法

2.一个喵统计点名串需要用个vis[],从黄学长哪里学到了黑科技用个vector记录vis了那些,不用memset直接把vector里的还原行了

3.可能有重复点名串!!!!!

4.姓和名用个特殊数字连起来行了

980ms

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
const int N=1e5+,INF=1e9;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
} int n,m,k;
vector<int> a[N];
struct node{
map<int,int> ch;
int fail,val;
vector<int> s;
}t[N];
int sz;
void ins(int id){
int u=,n=read();
for(int i=;i<=n;i++){
int c=read();
if(!t[u].ch[c]) t[u].ch[c]=++sz;
u=t[u].ch[c];
}
t[u].s.push_back(id);
}
int q[N],head,tail;
map<int,int>::iterator it,it2;
void getAC(){
head=tail=;
for(it=t[].ch.begin();it!=t[].ch.end();it++)
q[tail++]=it->second;
while(head!=tail){
int u=q[head++];
for(it=t[u].ch.begin();it!=t[u].ch.end();it++){
int v=it->second,c=it->first;
int now=t[u].fail;
while(now&&!t[now].ch.count(c)) now=t[now].fail;
if(t[now].ch.count(c)) t[v].fail=t[now].ch[c];
else t[v].fail=now;//
q[tail++]=v;
}
}
} int a1[N],a2[N];
bool vis[N];
vector<int> V;
void update(int u,int id){
for(;u;u=t[u].fail){
if(vis[u]) break;
vis[u]=;
V.push_back(u);
for(int i=;i<t[u].s.size();i++)
a1[t[u].s[i]]++,a2[id]++;
}
}
void runAC(int id){
vector<int> &s=a[id];
int u=,n=s.size();
for(int i=;i<n;i++){
while(u&&!t[u].ch.count(s[i])) u=t[u].fail;
if(t[u].ch.count(s[i])) u=t[u].ch[s[i]];
update(u,id);
}
for(int i=;i<V.size();i++) vis[V[i]]=;
V.clear();
}
void solve(){
getAC();
for(int i=;i<=n;i++) runAC(i);
for(int i=;i<=m;i++) printf("%d\n",a1[i]);
for(int i=;i<=n;i++) {printf("%d",a2[i]);if(i!=n) putchar(' ');}
}
int main(){
freopen("in","r",stdin);
n=read();m=read();
for(int i=;i<=n;i++){
k=read();while(k--) a[i].push_back(read());
a[i].push_back(-);
k=read();while(k--) a[i].push_back(read());
}
for(int i=;i<=m;i++) ins(i);
solve();
}

BZOJ 2754: [SCOI2012]喵星球上的点名 [AC自动机+map+暴力]的更多相关文章

  1. BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机+map维护Trie树)

    题目大意:略 由于字符集大,要用map维护Trie树 并不能用AC自动机的Trie图优化,不然内存会炸 所以我用AC自动机暴跳fail水过的 显然根据喵星人建AC自动机是不行的,所以要根据问题建 然而 ...

  2. BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机、树状数组)

    吐槽: 为啥很多人用AC自动机暴力跳都过了?复杂度真的对么? 做法一: AC自动机+树状数组 姓名的问题,中间加个特殊字符连起来即可. 肯定是对点名串建AC自动机(map存儿子),然后第一问就相当于问 ...

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

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 649  Solved: 305[Submit][Sta ...

  4. BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1906  Solved: 839[Submit][St ...

  5. 【刷题】BZOJ 2754 [SCOI2012]喵星球上的点名

    Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点 ...

  6. BZOJ2754: [SCOI2012]喵星球上的点名(AC自动机)

    Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2816  Solved: 1246[Submit][Status][Discuss] Descript ...

  7. BZOJ2754: [SCOI2012]喵星球上的点名(AC自动机/后缀自动机)

    Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串 ...

  8. bzoj 2754 [SCOI2012]喵星球上的点名(后缀数组)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2754 [题意] 每只喵有名姓,如果被老师点到名或姓的子串都要答道,但每只喵一次点名只答 ...

  9. bzoj 2754: [SCOI2012]喵星球上的点名【AC自动机】

    洛谷90,最后一个点死活卡不过去(也可能是我写的有问题? 比较暴力的做法,把询问带着标号建立AC自动机,用map存儿子. 然后用名字串在自动机上跑,以为是名或姓的子串就行所以把名和姓中间加个特殊字符拼 ...

随机推荐

  1. sql server 2008 r2 数据库操作时提示 9002错误“事物日志已满”问题

    事务日志截断 若要避免数据库的事务日志被填满,例行备份至关重要.在简单恢复模式下,备份了数据库后会自动截断日志,而在完整恢复模式下,只有备份了事务日志后方才截断日志.但是,截断过程有时也可能发生延迟. ...

  2. 用NPOI导出Excel,生成下拉列表、以及下拉联动列表(第1篇/共3篇)

    最近帅帅的小毛驴遇到一个很奇葩的需求: 导出Excel报表,而且还要带下拉框,更奇葩的是,下拉框还是联动的. 小毛驴一天比较忙,所以这等小事自然由我来为她分忧了.经历了两天,做了几种解决方案,最后完美 ...

  3. 详解String类中的intern()方法

    我们用一个经典的例子来理解 package com.jvm.heap; public class MyTest { public static void main(String[] args) { S ...

  4. dede织梦栏目页和文章页中获取当前栏目名称方法

    一般情况下,在dede织梦系统中列表页.栏目页和文章页中获取当前所在栏目名称只需要代码:{dede:type}[field:typename]{/dede:type}即可,不需要定义ID,默认的就是当 ...

  5. 在ARC下,assign和weak的区别

    用了很久,却不知道它俩究竟有什么区别,作为一个新手来说,光会用不行,还要懂得原理. 首先说说区别:weak只可以修饰对象                    assign既可以修饰对象也可以修饰基本 ...

  6. Eclipse报错An internal error occurred during: "J2EE Component Mapping Update". java.lang.NullPointerException

    Eclipse每次打开.java文件时,报错信息如下: An internal error occurred during: "J2EE Component Mapping Update&q ...

  7. ADO.NET复习总结(1)--ADO.NET基础介绍

    1.为什么要学ADO.NET: 之前我们所学只能在查询分析器里查看数据,操作数据,我们不能让普通用户去学sql, 所以我们搭建一个界面(Web或Winform)让用户方便的操作数据库中的数据. 2.什 ...

  8. Java 中判断类和实例之间的关系

    判断类与实例的关系有以下三种方式 1.instanceof关键字,用来判断对象是否是类的实例 (对象 => 类 )   2.isAssignableFrom,用来判断类型间是否存在派生关系 (类 ...

  9. 用Express、MySQL搭建项目(接口以及静态文件获取、文件上传等)

    一.简介 本文将主要基于node.js使用express框架搭建一个后台环境,包括如何自定义项目目录.所用依赖以及中间件.路由以及模板引擎.接口数据获取以及文件上传等内容. 二.后台环境搭建 1.新建 ...

  10. SpringMvc4.x--Spring MVC的常用注解

    //下列代码显示用到的对象public class DemoObj { private Long id; private String name; public DemoObj() { //① sup ...