bzoj 3172 单词 ac自动机|后缀数组
题目大意:
给定n个字符串连成了一篇文章,问每个字符串在这篇文章中出现的次数,可重复覆盖
这里ac自动机和后缀数组都可以做
当然后缀数组很容易就解决,但是相对时间消耗高
这里就只讲ac自动机了
将每个字符串放入ac自动机中,这里需要记录到达每个ac自动机上的节点出现这个状态有多少次
而我们添加字符串进入的时候,应该是把经过的每个节点的val都++,说明这个字符串多出现了一次这个值
然后因为自己用字符串在ac自动机上走肯定是到达离root最近的点,也就是说有很多的点会不断通过fail指针指向他,而这些点都是包含了这个字符串的
那也就是说我们需要考虑 val[fail[i]] += val[i]
这里一定是需要从最底层的点不断fail上来,我们需要找到一个合适的更新val点的顺序
可以考虑在我们构建后缀自动机的时候我们采用的是利用队列bfs的过程,那也就是说进入的点是符合最大长度从小到大的性质的
而fail指向的总是比它长度更小的点,所以根据进入队列的点的逆顺序来更新val即可
也就是每次点进队列都 que[cnt++] = u;
最后
for(int i=sz-1 ; i>0 ; i--)
val[fail[que[i]]]+=val[que[i]];
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
#define clr(x) memset(x , 0 , sizeof(x))
#define set(x) memset(x , -1 , sizeof(x))
typedef long long LL ; const int CHAR_SIZE = ;
const int MAX_SIZE = ;
const int M = ; struct AC_Machine{
int ch[MAX_SIZE][CHAR_SIZE] , val[MAX_SIZE] , fail[MAX_SIZE] , que[MAX_SIZE];
int sz;
bool vis[MAX_SIZE];
void init(){
sz = ;
clr(ch[]) , clr(val) , clr(vis);
} int insert(string s){
int n = s.length();
int u= ;
for(int i= ; i<n ; i++){
int c = s[i]-'a';
if(!ch[u][c]){
clr(ch[sz]) , val[sz]=;
ch[u][c] = sz++;
}
u = ch[u][c];
val[u]++;
}
return u;
} void get_fail(){
queue<int> Q;
fail[] = ;
int cnt = ;
for(int c= ; c<CHAR_SIZE ; c++){
int u = ch[][c];
if(u){Q.push(u);fail[u]=,que[cnt++]=u;}
}
while(!Q.empty()){
int r = Q.front();
Q.pop();
for(int c= ; c<CHAR_SIZE ; c++){
int u = ch[r][c];
if(!u){ch[r][c] = ch[fail[r]][c]; continue;}
fail[u] = ch[fail[r]][c];
Q.push(u);
que[cnt++]=u;
}
}
}
void updateVal(){
for(int i=sz- ; i> ; i--)
val[fail[que[i]]]+=val[que[i]];
}
}ac;
int n , pos[];
string s[]; int main()
{
// freopen("a.in" , "r" , stdin);
// freopen("out.txt" , "w" , stdout);
scanf("%d" , &n);
ac.init();
for(int i= ; i<n ; i++){
cin>>s[i];
pos[i] = ac.insert(s[i]);
}
ac.get_fail();
ac.updateVal();
for(int i= ; i<n ; i++)
printf("%d\n" , ac.val[pos[i]]);
return ;
}
bzoj 3172 单词 ac自动机|后缀数组的更多相关文章
- 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机
为何scanf("%s", str)不需要&运算 经常忘掉的字符串知识点,最好不加&,不加&最标准,指针如果像scanf里一样加&是错的,大概是未定 ...
- Trie树&kmp&AC自动机&后缀数组&Manacher
Trie 计数+Trie,读清题意很重要 https://vjudge.net/problem/UVALive-5913 kmp AC自动机 模板:https://vjudge.net/problem ...
- (17/34)AC自动机/后缀数组/后缀自动机(施工中)
快补题别再摸鱼了(17/34) 1.AC自动机 #define maxnode 1000010 #define maxsize 26 struct ahocT{ int ch[maxnode][max ...
- BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]
3172: [Tjoi2013]单词 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 3198 Solved: 1532[Submit][Status ...
- BZOJ 3172 单词(ac自动机)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3172 题意:给出n个单词.输出每个单词在所有单词中一共出现多少次? 思路:首先将所有单词 ...
- bzoj 3172: [Tjoi2013]单词 AC自动机
3172: [Tjoi2013]单词 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- 【BZOJ 3172】[Tjoi2013]单词 AC自动机
关于AC自动机:一个在kmp与Trie的基础上建立的数据结构,关键在于Trie树结构与fail指针,他们各有各的应用.在AC自动机里最典型的就是多串匹配,原本效率为O(n*l+n*l+m*l),(n是 ...
- BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树
Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...
- bzoj 3796: Mushroom追妹纸 AC自动机+后缀自动机+dp
题目大意: 给定三个字符串s1,s2,s3,求一个字符串w满足: w是s1的子串 w是s2的子串 s3不是w的子串 w的长度应尽可能大 题解: 首先我们可以用AC自动机找出s3在s1,s2中出现的位置 ...
随机推荐
- 测试oracle数据库的脱机备份和恢复
环境:windows7.Oracle11g 一.脱机备份 脱机备份是指在数据库关闭情况下的数据备份,也称为冷备份. 在书上学到的备份步骤: 1.记录所要备份数据库文件所在的操作系统路径: 2.关闭数据 ...
- LINQ之路 9:LINQ to SQL 和 Entity Framework(上)
在上一篇中,我们从理论和概念上详细的了解了LINQ的第二种架构“解释查询”.在这接下来的二个篇章中,我们将使用LINQ to SQL和Entity Framework来实践“解释查询”,学习这些技术的 ...
- JAVA 1.8 理解面向对象程序设计
1. break语句:经常用在循环语句中,用于跳出整个循环,执行循环后面的代码. 2. continue语句:经常用在循环语句中,用于跳出当前的这个循环(或者是跳出本次循环),开始下一次循环的执行. ...
- venus
The Venus system was a small timesharing system serving five or six users at a time:分时系统 The design ...
- jsonp的使用
假设我们已经了解什么是同源策略,以及什么是浏览器的同源策略的限制. 现在我们需要在a.demo.com下的某个页面one.html 里加载不同域b.demo.com下的json数据. 我们都知道用&l ...
- 贪心算法(Greedy Algorithm)
参考: 五大常用算法之三:贪心算法 算法系列:贪心算法 贪心算法详解 从零开始学贪心算法 一.基本概念: 所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以 ...
- 【转】 linux内存管理
一 为什么需要使用虚拟内存 大家都知道,进程需要使用的代码和数据都放在内存中,比放在外存中要快很多.问题是内存空间太小了,不能满足进程的需求,而且现在都是多进程,情况更加糟糕.所以提出了虚拟内存,使得 ...
- Linux快捷键
欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...
- JQuery实现table分页
1.直接贴代码: ; //每页显示的记录条数 ; //显示第curPage页 var len; //总行数 var page; //总页数 $(function(){ len =$(; //去掉表头 ...
- Yii2使用教程
安装 中文文档:http://www.yiichina.com/doc/guide/2.0/start-installation 1,安装 这里我直接下载归档文件,压缩包安装了.composer各种麻 ...