博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【bzoj3172】 [Tjoi2013]单词 AC自动机
阅读量:5263 次
发布时间:2019-06-14

本文共 1508 字,大约阅读时间需要 5 分钟。

题目描述

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

输入

第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6

输出

输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。

样例输入

3

a
aa
aaa

样例输出

6

3
1


题解

AC自动机

由fail的定义,可知,求出现次数,就是求有多少个节点可以通过fail链到达目标串末端的位置。

那么我们可以建立一棵fail树,每个节点的子树都包含目标串。

那么答案就变成了子树中所有前缀出现的次数。

把每个字符串的每个节点权值+1,最后向上递推即可。

#include 
#include
#include
using namespace std;queue
q;int nt[201][26] , cnt[201] , tot = 1;bool f[1000001];char str[1000001];int main(){ int n , m , i , j , l , t , ans; scanf("%d%d" , &n , &m); while(n -- ) { scanf("%s" , str); l = strlen(str); t = 1; for(i = 0 ; i < l ; i ++ ) { if(!nt[t][str[i] - 'a']) nt[t][str[i] - 'a'] = ++tot; t = nt[t][str[i] - 'a']; } cnt[t] ++ ; } while(m -- ) { scanf("%s" , str); l = strlen(str); memset(f , 0 , sizeof(f)); f[0] = 1; for(i = 0 ; i < l ; i ++ ) { if(f[i]) { t = 1; j = i; while(nt[t][str[j] - 'a']) { t = nt[t][str[j ++ ] - 'a']; if(cnt[t]) f[j] |= f[i]; } } } for(i = 0 ; i <= l ; i ++ ) if(f[i]) ans = i; printf("%d\n" , ans); } return 0;}

转载于:https://www.cnblogs.com/GXZlegend/p/6264991.html

你可能感兴趣的文章
心得25--JDK新特性9-泛型1-加深介绍
查看>>
[转]ceph网络通信模块_以monitor模块为例
查看>>
HDOJ 1754 I Hate It(线段树基本操作)
查看>>
latex tree
查看>>
安装NVIDIA驱动时禁用自带nouveau驱动
查看>>
HDU-1255 覆盖的面积 (扫描线)
查看>>
css3学习01
查看>>
【USACO】 奶牛会展
查看>>
ActiveMQ笔记之点对点队列(Point-to-Point)
查看>>
继承和多态
查看>>
Dijkstra+计算几何 POJ 2502 Subway
查看>>
修复IE不能执行JS的方法
查看>>
程序员究竟该如何提高效率zt
查看>>
希尔排序法(缩小增量法)
查看>>
PHP编程基础学习(一)——数据类型
查看>>
MongoDB-JAVA-Driver 3.2版本常用代码全整理(2) - 查询
查看>>
NPOI处理Word文本中上下角标
查看>>
Android笔记 Handler
查看>>
如何阅读大型前端开源项目的源码(转)
查看>>
java.util.Arrays类详解
查看>>