【题目大意】

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. 简单瞎搞题(bitset的操作)

    链接:https://www.nowcoder.com/acm/contest/132/C来源:牛客网 题目 一共有 n个数,第 i 个数是 xi  xi 可以取 [li , ri] 中任意的一个值. ...

  2. oracle导入和导出和授权

    导入数据库: imp demo@orcl file=d:/bak_1023.dmp full=y ignore=y 导出数据库: @orcl file=d:/bak_1023.dmpexp yhtj/ ...

  3. 【比赛】百度之星2017 初赛Round A

    第一题 题意:给定多组数据P,每次询问P进制下,有多少数字B满足条件:只要数位之和是B的倍数,该数字就是B的倍数. 题解:此题是参考10进制下3和9倍数的特殊性质. 对于10进制,ab=10*a+b= ...

  4. HDU1003MAX SUM (动态规划求最大子序列的和)

    Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  5. 滑杆(JSlider)和进度指示条(JProgressBar) 的使用

    package first; import javax.swing.*; import javax.swing.border.TitledBorder; import java.awt.*; impo ...

  6. [bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式——后缀数组

    Brief Description 给定一个字符串,求至少出现k次的最长重复子串. Algorithm Design 先二分答案,然后将后缀分成若干组.判断有没有一个组的后缀个数不小于k.如果有,那么 ...

  7. JavaScript DOM编程艺术 读书笔记

    2. JavaScript语法 2.1 注释      HTML允许使用"<!--"注释跨越多个行,但JavaScript要求这种注释的每行都必须在开头加上"< ...

  8. MySQL MyISAM优化设置点滴

    先说一点问题:   Mysql中的InnoDB和MyISAM是在使用MySQL中最常用的两个表类型,各有优缺点.两种类型最主要的差别就是 InnoDB 支持事务处理与外键和行级锁.而MyISAM不支持 ...

  9. Shell Script Basics

    https://developer.apple.com/library/mac/documentation/OpenSource/Conceptual/ShellScripting/shell_scr ...

  10. python基础===两个list合并成一个dict的方法

    def Run(): list2 = [, , , , ]; list3 = ["a", "b", "c", "d",& ...