题面:

洛谷

题解:

  很久之前做的题了,只不过之前一直90.。。。最近才发现是哪里写错了。

  我们对字符集建AC自动机。

  首先考虑一个暴力的做法,把文章当做一个长串,直接在自动机上跳,但是我们会发现,这样的复杂度可能退化到$n^2$.

  因为对于一个类似于aaaaaaaaaaaaaaaa这样的串而言,一个点的fail总是指向它的父亲,因此如果我们每次都暴力向上跳fail复杂度就不对了。

  观察到每遍历到一个节点,其实质就是给这个点到root的这条链上的每个点都+1,因此我们目标只是在fail树上对每个点都求出子树和。

  如果我们知道了所有标记的位置,显然可以建树统计一下。

  当然,也有更方便的写法,因为一个点的编号肯定比它的fail的编号大。表现在fail树上就是父亲编号比儿子小。

  所以我们从大到小枚举编号,把当前枚举到的节点的权值加给父亲即可。

  为什么这样是对的?

    因为我们可以看做是儿子先把代价给父亲,在让父亲把它的代价和它儿子的代价一起向上传。

  

  其实对于这道题而言,还有更方便的写法,你甚至不需要建匹配串。因为文章就是由给定字符集组成的,因此我们一定会遍历自动机上的每一个节点,所以与其再遍历一遍,再把每个节点权值+1,不如在建自动机的时候就直接加。

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define maxn 2500500
int n,ans[maxn],go[maxn],num;//num标记是第一个单词,便于处理单词重复的情况
int q[maxn],head,tail,tot;//从第一位开始存文本串
char s[maxn]; struct ACtree
{
int fail[maxn], c[maxn][];
//由于是统计单词在文章中的出现次数,相同单词只算一次,所以val最大只能为1
void add()//标记是第一个单词
{
int now=,len=strlen(s);
for(R i=;i<len;i++)
{
int v=s[i]-'a';
if(!c[now][v]) c[now][v]=++tot;
now=c[now][v], ++ ans[now];//因为之后再遍历也是直接遍历整个树,所以直接在这里加
}
// if(!val[now])val[now]++;//这样val就没用了
go[num]=now;//记录下每个单词的结尾部分,以防遇到重复只输出一个
} void build()
{
R now;
for(R i=; i< ;i++)
if(c[][i]) q[++tail]=c[][i];//既然fail一开始都为0,那就不用额外初始化了
while(head<tail)
{
now=q[++head];
for(R i=;i<;i++)
if(c[now][i]) fail[c[now][i]]=c[fail[now]][i],q[++tail]=c[now][i];
else c[now][i]=c[fail[now]][i];//建立虚拟节点
}
for(R i = tail; i; i --) ans[fail[q[i]]] += ans[q[i]];
for(R i = ; i <= n; i ++) printf("%d\n", ans[go[i]]);
} }AC; void pre()
{
scanf("%d",&n);
for(num=; num<=n ;num++)
scanf("%s",s), AC.add();
} int main()
{
// freopen("in.in","r",stdin);
pre();
AC.build();
// fclose(stdin);
return ;
}

  

[TJOI2013]单词 AC自动机的更多相关文章

  1. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

  2. 【BZOJ3172】[Tjoi2013]单词 AC自动机

    [BZOJ3172][Tjoi2013]单词 Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input ...

  3. bzoj 3172: [Tjoi2013]单词 AC自动机

    3172: [Tjoi2013]单词 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  4. 洛谷P3966 [TJOI2013]单词(AC自动机)

    题目描述 小张最近在忙毕设,所以一直在读论文.一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 输入输出格式 输入格式: 第一行一个整数N,表 ...

  5. [TJOI2013]单词 AC 自动机

    题目描述: 小张最近在忙毕设,所以一直在读论文. 一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 题解: AC 自动机裸题,将所有字符串读入 ...

  6. 【BZOJ 3172】[Tjoi2013]单词 AC自动机

    关于AC自动机:一个在kmp与Trie的基础上建立的数据结构,关键在于Trie树结构与fail指针,他们各有各的应用.在AC自动机里最典型的就是多串匹配,原本效率为O(n*l+n*l+m*l),(n是 ...

  7. BZOJ3172[Tjoi2013]单词——AC自动机(fail树)

    题目描述 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. 输入 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个 ...

  8. BZOJ 3172 [Tjoi2013]单词 AC自动机Fail树

    题目链接:[http://www.lydsy.com/JudgeOnline/problem.php?id=3172] 题意:给出一个文章的所有单词,然后找出每个单词在文章中出现的次数,单词用标点符号 ...

  9. bzoj3172: [Tjoi2013]单词 ac自动机

    某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个单词 ...

随机推荐

  1. JUnit在intellij idea中只能在test里面才能使用,否则不能添加import

    只能在 src下的test下使用 不能再main下使用 否则不能import到指定的junit包 idea这样做的好处就是分离主项目和测试项目,这样一来就能够更加方便的测试了 如图直接这样把整个主包  ...

  2. RestQL:现代化的 API 开发方式

    参考:https://tech.meituan.com/koa-restql.html 在现代的业务系统中,后端开发工作基本上可以被拆分为三项: 接口鉴权.例如判断是不是当前系统的用户,以及该用户是否 ...

  3. arcpy示范教学(一):基本操作

    arcpy基本操作 打开目录,遍历目录,打开要素类,遍历要素,打开文件,写入属性值 import arcpy import codecs # 设置工作目录 arcpy.env.workspace = ...

  4. 如何下载YouTube 60fps视频

    YouTube上面不仅支持分辨率为4K和8K的视频,同时也开启了对60fps视频的支持.60帧的视频广泛用于游戏和体育视频中,使视频看起来更加流畅和细腻.对游戏玩家来说,YouTube对60fps支持 ...

  5. 420. Count and Say【LintCode java】

    Description The count-and-say sequence is the sequence of integers beginning as follows: 1, 11, 21, ...

  6. 排序(C语言实现)

    读数据结构与算法分析 插入排序 核心:利用的是从位置0到位置P都是已排序的 所以从位置1开始排序,如果当前位置不对,则和前面元素反复交换重新排序 实现 void InsertionSort(Eleme ...

  7. 用 Python 3 的 async / await 做异步编程

    前年我曾写过一篇<初探 Python 3 的异步 IO 编程>,当时只是初步接触了一下 yield from 语法和 asyncio 标准库.前些日子我在 V2EX 看到一篇<为什么 ...

  8. python3【基础】-集合

    集合( set):把不同的元素组成一起形成集合,是python基本的数据类型. 集合元素(set elements):组成集合的成员(不可重复) class set(object) | set() - ...

  9. Knight Moves(广搜BFS)

    Description A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to ...

  10. Floyd模板(详细操作最基础版)

    #include<cstdio> #include<iostream> using namespace std; #define MAX 500 #define INFE 1& ...