【题目大意】

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. Fabric证书解析

    一.证书目录解析   通过cryptogen生成所有证书文件后,以peerOrgannizations的第一个组织树org1为例,每个目录和对应文件的功能如下:   ca: 存放组织的根证书和对应的私 ...

  2. Codeforces Round #350 (Div. 2) C

    C. Cinema time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  3. springboot之模板

    转:http://jisonami.iteye.com/blog/2301387,http://412887952-qq-com.iteye.com/blog/2292402 整体步骤:(1)     ...

  4. JS中二维数组的声明

    var myarr=new Array(); //先声明一维 for(var i=0;i<2;i++){ //一维长度为2 myarr[i]=new Array(); //再声明二维 for(v ...

  5. Git菜鸟

    1.git 和svn的差异 git和svn 最大的差异在于git是分布式的管理方式而svn是集中式的管理方式.如果不习惯用代码管理工具,可能比较难理解分布式管理和集中式管理的概念.下面介绍两种工具的工 ...

  6. 线段树+矩阵快速幂 Codeforces Round #373 (Div. 2) E

    http://codeforces.com/contest/719/problem/E 题目大意:给你一串数组a,a[i]表示第i个斐波那契数列,有如下操作 ①对[l,r]区间+一个val ②求出[l ...

  7. MySQL 进阶(待发布)

    视图 存储过程 触发器 基本函数

  8. 图像转换为二进制文件存入DSP6748

    本文为原创作品,转载请注明出处 欢迎关注我的博客:http://blog.csdn.net/hit2015spring和http://www.cnblogs.com/xujianqing/ 这篇博客主 ...

  9. gdb 调试 ncurses 全过程:

    转载地址: http://blog.jobbole.com/107759/ gdb 调试 ncurses 全过程: 发现网上的“gdb 示例”只有命令而没有对应的输出,我有点不满意.gdb 是 GNU ...

  10. centos7.3安装caffe出现错误:/bin/ld: cannot find -lcblas /bin/ld: cannot find -latlas

    安装caffe时需要依赖库atlas,可使用yum -y install atlas-devel  安装,但是安装之后还是有可能出现错误: /bin/ld: cannot find -lcblas / ...