BZOJ_3172_[TJOI2013]_单词_(AC自动机)
2016-07-06 18:14
351 查看
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=3172
\(n\)个单词组成一篇文章,求每个单词在文章中出现的次数.
分析
这道题很像BZOJ_2434_[NOI2011]_阿狸的打字机_(AC自动机+dfs序+树状数组)
一个单词出现过,那么一定是某个单词的某个前缀的后缀,可以通过这个前缀的末尾沿着失配边找到它.我们要统计有多少点可以这样找到它.
建立fail树,很显然,单词\(x\)子树中的所有点都可以沿着失配边找到\(x\),这样我们只用记录每个点有多少次就行了.
(eg:如果文章是 a aa aaa,那么a有3次(三个单词各一次),aa有2次(第二个单词和第三个单词),aaa有1次(第三个单词)).
#include <bits/stdc++.h> using namespace std; const int maxn=1e6+10,type=26; int n,m; char s[maxn]; struct Aho_Corasick{ int sz; int q[maxn],val[maxn],pos[maxn],f[maxn]; int ch[maxn][type]; Aho_Corasick():sz(0){memset(ch[0],0,sizeof ch[0]);memset(val,0,sizeof val);} inline int insert(char *s){ int u=0,m=strlen(s+1); for(int i=1;i<=m;i++){ int c=s[i]-'a'; if(!ch[u][c]){ memset(ch[++sz],0,sizeof ch[sz]); val[sz]=0; ch[u][c]=sz; } u=ch[u][c]; val[u]++; } return u; } inline void get_fail(){ int L=1,R=0; for(int c=0;c<type;c++){ int u=ch[0][c]; if(u){f[u]=0;q[++R]=u;} } while(L<=R){ int u=q[L++]; for(int c=0;c<type;c++){ int t=ch[u][c]; if(!t){ch[u][c]=ch[f[u]][c];continue;} int v=f[u]; f[t]=ch[v][c]; q[++R]=t; } } for(int i=sz;i;i--) val[f[q[i]]]+=val[q[i]]; } inline void solve(){ for(int i=1;i<=n;i++) printf("%d\n",val[pos[i]]); } }ac; inline void solve(){ ac.get_fail(); ac.solve(); } inline void init(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",s+1); ac.pos[i]=ac.insert(s); } } int main(){ init(); solve(); return 0; }View Code
3172: [Tjoi2013]单词
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2837 Solved: 1356
[Submit][Status][Discuss]
Description
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
Input
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
Output
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
Sample Input
3a
aa
aaa
Sample Output
63
1
HINT
Source
相关文章推荐
- iOS开发之都兴忱小结
- Unity3D 5.3 新版AssetBundle使用方案及策略
- mysql mysql_error mysqli_connect_error 乱码
- C# 在字符串指定位置之前插入新的字符串
- Spark SQL 官方文档-中文翻译
- Unity3D命令行Build
- 分布式系统架构——Mysql数据库实现主从同步
- java读源文件写入目标文件
- 视频解析 --libcef
- Zend与PHP之间到底是什么关系
- Python入门:验证码破解(二)
- linux fdisk运用
- cmake 学习初级篇
- nginx 查看访问 IP 并封禁 IP 详解
- USB unavailable after update kernel
- transfer between javabean and map
- 重新排列数组使得左边为奇数,右边为偶数
- 一些好玩的题目
- MySQL数据类型及字段属性
- 二分:电脑配件购置