【题目大意】

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. vm虚拟机 开启时报错 无法打开内核设备“\\.\Global\vmx86”: 系统找不到指定的文件。

    解决办法 方案一 1/http://jingyan.baidu.com/article/455a9950aaf4aea167277878.html 方案二 2.http://jingyan.baidu ...

  2. Firefox多国语言多OS离线安装包

    Download Firefox in your language Firefox is made in large part by volunteers around the world. That ...

  3. Hibernate 懒加载 错误----no session

    错误: unable to evaluate the expression Method threw 'org.hibernate.LazyInitializa org.hibernate.LazyI ...

  4. MyBatis对象关联关系---- association与collection

    Mybatis处理“一对多”的关系时,需要用到associasion元素.处理”多对一“用collection元素来实现(这两个元素在之前mapper文件中提到过). 本例子中,假设一名User可以有 ...

  5. 转:nginx入门指南,快速搭建静态文件服务器和代理服务器

    本文介绍 Nginx 入门基础知识,让你迅速搭建 Nginx 服务器.主要内容包括 Nginx 安装和简单使用.Nginx的简单原理.Nginx 配置文件的结构.如何使用 Nginx 来提供静态文件服 ...

  6. 用 letsencrypt 生成 SSL 证书

    letsencrypt 生成 SSL 证书 事先配置好访问域名解析 在nginx 对应虚拟主机添加一个验证区域: 配置 nginx server { listen 80; ... location ~ ...

  7. 密码框JPasswordField 的使用

    JPasswordField的主要方法为setEchoChar(char c),其中的字符C为回显字符. package first; import javax.swing.*; import jav ...

  8. KMP算法_模板_C++

    这个博客讲得非常优秀,可惜它是Java版本的 http://blog.csdn.net/yutianzuijin/article/details/11954939/ a 为匹配串,b 为目标串 通俗讲 ...

  9. poj 1528 Perfection

    题目链接:http://poj.org/problem?id=1528 题目大意:输入一个数n,然后求出约数的和sum,在与这一个数n进行比较,如果sum>n,则输出ABUNDANT,如果sum ...

  10. 【反演复习计划】【bzoj3994】DZY loves maths

    这题大概就是提取一下d,然后就跟前面的题目差不多了. #include<bits/stdc++.h> #define N 10000005 using namespace std; typ ...