[BZOJ3172][TJOI2013]单词(AC自动机)
2016-04-04 17:25
435 查看
题目描述
传送门题解
记录每一个点建自动机时候的访问次数。建Fail树,然后节点子树的大小即为当前点出现的次数。
代码
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int max_n=2e2+5; const int max_s=1e6+5; int n,pos[max_n]; int tot,ans[max_s],query[max_s],cnt; char s[max_s]; int ch[max_s][30],fail[max_s]; queue <int> q; inline void insert(int &loc){ int now=0,len=strlen(s); for (int i=0;i<len;++i){ int x=s[i]-'a'; if (!ch[now][x]) ch[now][x]=++tot; now=ch[now][x]; ++ans[now]; } loc=now; } inline void make_fail(){ while (!q.empty()) q.pop(); for (int i=0;i<26;++i) if (ch[0][i]) q.push(ch[0][i]); while (!q.empty()){ int now=q.front(); q.pop(); query[++cnt]=now; for (int i=0;i<26;++i){ if (!ch[now][i]){ ch[now][i]=ch[fail[now]][i]; continue; } fail[ch[now][i]]=ch[fail[now]][i]; q.push(ch[now][i]); } } } inline void calc_ans(){ for (int i=cnt;i>=1;--i) ans[fail[query[i]]]+=ans[query[i]]; } int main(){ scanf("%d\n",&n); for (int i=1;i<=n;++i){ gets(s); insert(pos[i]); } make_fail(); calc_ans(); for (int i=1;i<=n;++i) printf("%d\n",ans[pos[i]]); }
总结
Fail神奇的特性:所有以x节点代表的字符串结尾的字符串节点,都在x的子树中。相关文章推荐
- mysql函数编写和存储过程
- FILE结构体
- 编写ATL工程实现ActiveX控件调用cryptoAPI接口(四)------------Base64转码
- 小猫统计:部分解决安装问题
- Jmeter与Jenkins的集成
- UVa 11292&HDU1902 The Dragon of Loowater (贪心)
- jqueryui.position.js源代码分析
- SBT平衡树
- HDU-4966 GGS-DDU (最小树形图(有向图的最小生成树)[朱刘算法])
- 使用matlab验证modelview矩阵
- jQuery ui
- Poj 2010 Moo University - Financial Aid【优先队列+神技巧】
- 再议浮点数
- 【01背包】Charm Bracelet
- SQL Server 2008 R2提示评估过期
- 调用cryptlib接口3DES对称加密、信封加密、数字签名等
- JDK自带Tools(预览)
- 全面介绍Android的MVVM框架 - 数据绑定
- nyist 746 整数划分(四)(经典DP)
- 如何利用十行代码,绕过杀毒软件实现免杀?