【BZOJ3172】单词(AC自动机)
【BZOJ3172】单词(AC自动机)
题面
Description
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
Input
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
Output
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
Sample Input
3
a
aa
aaa
Sample Output
6
3
1
题解
yyb因为调这道题而死亡
在重复一下题目的意思把。。。
看不见文章对不读,,
那是因为文章就是所有单词组成的
然后你就可以yy所有单词中间有一个空格之类的东西
很明显的AC自动机,
然后,我们
每次把每个单词带进去匹配一下
暴跳fail指针
美滋滋的收获90分
0分是空间玩炸了。。。
暴跳fail指针是可以被卡炸的。。。
所以,我们就不暴跳了呀
每次要跳的时候就在这个点这里打一个标记
所有标记打完之后
我们就从底下往上一层层跳(记一下bfs序倒着跳)
每次就只跳一层,然后标记丢到上面去
这样就可以一起跳啦
然后美滋滋的 AC啦
对了,
这题还有一点
就是会有重复的单词。。。
所以要记录一下每个单词和哪个单词是一样的(不是并查集)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 1100000
struct Node
{
int vis[26];
int fail,ff;
int id,sum;
}t[MAX];
int tot,lid[500];
int ans[500];
int n,q[MAX],tp;
char ch[MAX],ss[MAX];
void Insert(int id,char *s)
{
int gg=strlen(s);
int now=0;
for(int i=0;i<gg;++i)
{
if(!t[now].vis[s[i]-'a'])
t[now].vis[s[i]-'a']=++tot;
t[t[now].vis[s[i]-'a']].ff=now;
now=t[now].vis[s[i]-'a'];
}
if(!t[now].id)t[now].id=id,lid[id]=id;
else lid[id]=t[now].id;
}
queue<int> Q;
void GetFail()
{
for(int i=0;i<26;++i)
if(t[0].vis[i])
Q.push(q[++tp]=t[0].vis[i]);
while(!Q.empty())
{
int u=Q.front();Q.pop();
for(int i=0;i<26;++i)
{
if(t[u].vis[i])
t[t[u].vis[i]].fail=t[t[u].fail].vis[i],Q.push(q[++tp]=t[u].vis[i]);
else
t[u].vis[i]=t[t[u].fail].vis[i];
}
}
}
int l=0;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%s",ch);
Insert(i,ch);
int len=strlen(ch);
for(int j=0;j<len;++j)
ss[l++]=ch[j];
ss[l++]='#';
}
GetFail();
int now=0;
for(int j=0;j<l;++j)
{
if(ss[j]=='#')now=0;
else now=t[now].vis[ss[j]-'a'];
t[now].sum++;
}
for(int i=tp;i;i--)
{
ans[t[q[i]].id]+=t[q[i]].sum;
t[t[q[i]].fail].sum+=t[q[i]].sum;
}
for(int i=1;i<=n;++i)printf("%d\n",ans[lid[i]]);
return 0;
}
【BZOJ3172】单词(AC自动机)的更多相关文章
- 【BZOJ3172】[Tjoi2013]单词 AC自动机
[BZOJ3172][Tjoi2013]单词 Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input ...
- BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]
3172: [Tjoi2013]单词 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 3198 Solved: 1532[Submit][Status ...
- 洛谷P3966 [TJOI2013]单词(AC自动机)
题目描述 小张最近在忙毕设,所以一直在读论文.一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 输入输出格式 输入格式: 第一行一个整数N,表 ...
- BZOJ2905: 背单词 AC自动机+fail树+线段树
$zjq$神犇一眼看出$AC$自动机 $Orz$ 直接就讲做法了 首先对每个串建出$AC$自动机 将$fail$树找到 然后求出$dfs$序 我们发现一个单词 $S_i$是$S_j$的子串当且仅当$S ...
- [TJOI2013]单词 AC自动机
题面: 洛谷 题解: 很久之前做的题了,只不过之前一直90....最近才发现是哪里写错了. 我们对字符集建AC自动机. 首先考虑一个暴力的做法,把文章当做一个长串,直接在自动机上跳,但是我们会发现,这 ...
- bzoj 3172: [Tjoi2013]单词 AC自动机
3172: [Tjoi2013]单词 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- [TJOI2013]单词 AC 自动机
题目描述: 小张最近在忙毕设,所以一直在读论文. 一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 题解: AC 自动机裸题,将所有字符串读入 ...
- BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树
Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...
- toj 4063 单词(AC自动机)
题目: 小张最近在忙毕设,所以一直在读论文.一篇论文是由许多单词组成的. 但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 输入 第一行一个整数N,表示有N个单词.接 ...
- bzoj 3172 单词 ac自动机|后缀数组
题目大意: 给定n个字符串连成了一篇文章,问每个字符串在这篇文章中出现的次数,可重复覆盖 这里ac自动机和后缀数组都可以做 当然后缀数组很容易就解决,但是相对时间消耗高 这里就只讲ac自动机了 将每个 ...
随机推荐
- PHP两个日期之间的所有日期
我想得到两个日期之间的所有日期, 例如:输入两个日期,把这两个日期之间的所有日期取出来 如果是:2005-02-01至2005-02-05(同为一个月) 则为:2005-02-01,2 ...
- 使用CentOS Linux Bridge搭建Vxlan环境
一. 基础环境使用VmWare虚拟两台Linux机器.CentOS 7,Linux内核如下:4.5.3-1.el7.elrepo.x86_64如果内核版本太低,是不支持VxLan的.可以使用一下命令进 ...
- Linux 环境下程序不间断运行
一.背景 在linux命令行中执行程序,程序通常会占用当前终端,如果不启动新的终端就没法执行其他操作.简单可以通过'&'将程序放到后台执行,但是这种方法有个问题就是,一旦连接远程服务器 ...
- 记一次 bug 修复 , 未将对象引用实例化
我们对默认值的使用技巧中,同一个组件, 升级版本,增加新的配置字段,执行新的逻辑. 老版本,没有类似的配置字段,走原始逻辑. 在类的构造中,添加了这么一句代码, 运行后,报错,没看出问题原因: boo ...
- Navi.Soft31.任务管理器(定时同步+数据采集)
1系统简介 1.1功能简述 在众多的软件分类中,有几类的软件不是很重要,但也很重要.它们有的是每隔一段时间需要执行一些任务的软件,我们叫它定时类软件:还有一种软件是采集网页中的数据,我们叫它采集类软件 ...
- TP5整合 WorkerMan 以及 GatewayWorker
TP5整合GatewayWorker Windows版安装 a)使用composer create-project topthink/think testTG,来安装thinkphp5. b)进入t ...
- Mysql取随机数据效率测试(400W条中读取100条)
测试数据表的创建在文章:http://www.cnblogs.com/wt645631686/p/6868192.html 先看一下我的SQL方案 SELECT * FROM `emp` WHERE ...
- nyoj49 开心的小明 01背包
思路:dp(i, j)表示用金钱j去买前i个物品能得到的最大价值.转移方程dp(i, j) = max{dp(i-1, j), dp(i-1, j-p[i]) + p[i]*w[i]}. AC代码 # ...
- SpringBoot CGLIB AOP解决Spring事务,对象调用自己方法事务失效.
对于像我这种喜欢滥用AOP的程序员,遇到坑也是习惯了,不仅仅是事务,其实只要脱离了Spring容器管理的所有对象,对于SpringAOP的注解都会失效,因为他们不是Spring容器的代理类,Sprin ...
- javascript中快速求数组的全部元素的相加之和
js中快速求数组的全部元素的相加之和: var arr = [1,2,3,4,5];var sum = eval(arr.join('+')); console.log(sum); 运行结果: 15