【题目大意】

http://www.lydsy.com:808/JudgeOnline/problem.php?id=3172

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

【思路】

第一次写fail树。首先建立AC自动机,对于路径上的每一个点sum++,表示出现的次数。fail指针指向的后缀,如果从fail指针指向的点开始方向建立fail树,其子树的sum之和就等于以它作为后缀的串的总数,相当于它在文章中出现的个数。

*fail树好神奇啊,不过E数组到底应该开多大呢?struct类型的数组到底应该怎么计算空间呢?困惑。

【错误名】

AC自动机的fail指针建立错了…详细见注释。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define Lnum 26
using namespace std;
const int MAXN=;
const int MAXLEN=;
int n;
int cnt=;
struct ACauto
{
ACauto* next[Lnum];
ACauto* fail;
int id,sum;
ACauto()
{
for (int i=;i<Lnum;i++) next[i]=NULL;
fail=NULL;
sum=;
id=++cnt;
}
};
ACauto* rt=new ACauto();
ACauto* node[MAXN];
struct edge
{
ACauto* to;
edge* next;
edge()
{
to=NULL;
next=NULL;
}
};
edge* E[MAXLEN*Lnum]; void addedge(ACauto* u,ACauto* v)
{
edge* tmp=new edge;
tmp->to=v;
tmp->next=E[u->id];
E[u->id]=tmp;
} void insert(ACauto* rt,char* str,int order)
{
ACauto* tmp=rt;
int len=strlen(str);
for (int i=;i<len;i++)
{
int index=str[i]-'a';
if (tmp->next[index]==NULL)
tmp->next[index]=new ACauto();
tmp=tmp->next[index];
tmp->sum++;
}
node[order]=tmp;
} void build(ACauto* rt)
{
queue<ACauto*> que;
que.push(rt);
while (!que.empty())
{
ACauto* head=que.front();que.pop();
for (int i=;i<Lnum;i++)
{
if (head->next[i]!=NULL)
{
if (head==rt)
{
head->next[i]->fail=rt;
addedge(rt,head->next[i]);
}
else
{
ACauto* tmp=head->fail;
while (tmp!=NULL)
{
if (tmp->next[i]!=NULL)
{
head->next[i]->fail=tmp->next[i];
//指向最长的后缀,所以是tmp->next[i],而不是tmp
addedge(tmp->next[i],head->next[i]);
break;
}
else tmp=tmp->fail;
}
if (tmp==NULL)
{
head->next[i]->fail=rt;
addedge(rt,head->next[i]);
}
}
que.push(head->next[i]);
}
}
}
} void dfs(ACauto* rt)
{
for (edge* i=E[rt->id];i!=NULL;i=i->next)
{
dfs(i->to);
rt->sum+=i->to->sum;
}
} void init()
{
scanf("%d",&n);
char str[MAXLEN];
for (int i=;i<n;i++)
{
scanf("%s",str);
insert(rt,str,i);
}
build(rt);
} void getans()
{
dfs(rt);
for (int i=;i<n;i++) cout<<node[i]->sum<<endl;
} int main()
{
init();
getans();
return ;
}

【AC自动机/fail树】BZOJ3172- [Tjoi2013]单词的更多相关文章

  1. 【学习笔记】ac自动机&fail树

    定义 解决文本串和多个模式串匹配的问题: 本质是由多个模式串形成的一个字典树,由tie的意义知道:trie上的每一个节点都是一个模式串的前缀: 在trie上加入fail边,一个节点fail边指向这个节 ...

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

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

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

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

  4. BZOJ2905: 背单词 AC自动机+fail树+线段树

    $zjq$神犇一眼看出$AC$自动机 $Orz$ 直接就讲做法了 首先对每个串建出$AC$自动机 将$fail$树找到 然后求出$dfs$序 我们发现一个单词 $S_i$是$S_j$的子串当且仅当$S ...

  5. BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树

    Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...

  6. AC自动机 & Fail树 专题练习

    Fail树就是AC自动机建出来的Fail指针构成的树. [bzoj3172][xsy1713]单词 题意 给定一些单词,求每个单词在所有单词里面的出现次数. 分析 构建Fail树,记录每个单词最后一个 ...

  7. BZOJ2434 [Noi2011]阿狸的打字机 【AC自动机 + fail树 + 树状数组】

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 3610  Solved: 1960 [Submit][S ...

  8. AC自动机fail树小结

    建议大家学过AC自动机之后再来看这篇小结 fail树就是讲fail指针看做一条边连成的树形结构 fail指针在AC自动机中的含义是指以x为结尾的后缀在其他模式串中所能匹配的最长前缀的长度 所以在模式串 ...

  9. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

随机推荐

  1. [SDOI2011]消防/[NOIP2007] 树网的核

    消防 题目描述 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情,所以这个国家最兴旺的 ...

  2. C#弱引用

    加菲猫 Just have a little faith. C#弱引用 .NET框架提供了另一有趣的特色,被用于实现多样的高速缓存.在.NET中弱引用通过System.WeakReference类实现 ...

  3. 取消eslint对指定代码进行代码检测

    eslint配置了不允许使用alert,但是有个需求需要用到. //eslint-disable-next-line alert('测试'); 如上,即可跳过当前行代码检查了

  4. python中orm框架学习

    安装sqlalchemy pip3 install sqlalchemy 创建表结构: from sqlalchemy import Column,String,create_engine from ...

  5. IDEA无法编译java8的lambda表达式提示Error:(16, 48) java: -source 1.5 中不支持 lambda 表达式

    在idea中新建了一个java8的项目,但是写lambda表达式提示语法错误,提示如下错误信息: Error:(16, 48) java: -source 1.5 中不支持 lambda 表达式 (请 ...

  6. loj6100 「2017 山东二轮集训 Day1」第一题

    传送门:https://loj.ac/problem/6100 [题解] 我们考虑维护从某个端点开始的最长满足条件的长度,如果知道了这个东西显然我们可以用主席树来对每个节点建棵关于右端点的权值线段树, ...

  7. 金中欢乐赛 C题

    题目传送门 这道题 hash就可以写了 弄了半天有点智障 强行压一压就okay了的说 #include<cstdio> #include<cstring> #include&l ...

  8. Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨.  1.Java序列化与反序列化  Java序列化是指把Java对象转换为字节 ...

  9. bzoj 4569 [Scoi2016]萌萌哒 并查集 + ST表

    题目链接 Description 一个长度为\(n\)的大数,用\(S_1S_2S_3...S_n\)表示,其中\(S_i\)表示数的第\(i\)位,\(S_1\)是数的最高位,告诉你一些限制条件,每 ...

  10. java 聊天程序

    package cn.apr.chart; import java.net.*; import java.io.*; import java.util.*; public class ChatServ ...