bzoj 3172 [Tjoi2013]单词(fail树,DP)
2016-02-20 08:56
627 查看
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=3172
【题意】
题目的意思是这样的,给若干个单词,求每个单词在这一堆单词中的出现次数。 出题人语文水平高
【思路】
AC自动机. fail树
AC自动机中的fail指针指向该串的一个后缀,将fail指针反向后得到一棵fail树,利用getFail后的bfs序在树上进行DP统计出现次数。
在fail树上,父节点对应字符串是其子结点对应字符串的极大后缀。我们用sum[u]记录一个结点u被几个单词结点所经过,插入时顺便统计一下即可。设pos[i]为单词i在自动机上所对应的尾节点,那么这时候sum[pos[i]]是否为i的答案呢?不是。因为可能出现有一个字符串为abbabc,而i是abc的情况,这时候abc作为后缀出现但是并没有计数,对于结点u,我们应该将fail树上u->root路径上的所有节点的sum+=sum[u],这步操作只需要递推一下,这时候的sum[pos[i]]才是i的答案。
感觉与SAM中的p=>p->fa的思路挺像的。
【代码】
http://www.lydsy.com/JudgeOnline/problem.php?id=3172
【题意】
题目的意思是这样的,给若干个单词,求每个单词在这一堆单词中的出现次数。 出题人语文水平高
【思路】
AC自动机. fail树
AC自动机中的fail指针指向该串的一个后缀,将fail指针反向后得到一棵fail树,利用getFail后的bfs序在树上进行DP统计出现次数。
在fail树上,父节点对应字符串是其子结点对应字符串的极大后缀。我们用sum[u]记录一个结点u被几个单词结点所经过,插入时顺便统计一下即可。设pos[i]为单词i在自动机上所对应的尾节点,那么这时候sum[pos[i]]是否为i的答案呢?不是。因为可能出现有一个字符串为abbabc,而i是abc的情况,这时候abc作为后缀出现但是并没有计数,对于结点u,我们应该将fail树上u->root路径上的所有节点的sum+=sum[u],这步操作只需要递推一下,这时候的sum[pos[i]]才是i的答案。
感觉与SAM中的p=>p->fa的思路挺像的。
【代码】
#include<cstdio> #include<cstring> using namespace std; const int N = 1e6+10; struct ACauto { int sz,ch [26],sum ,q ,pos ,f ; void init() { sz=1; memset(ch[0],0,sizeof(ch[0])); } void insert(char* s,int rank) { int u=0; for(int i=0;s[i];i++) { int c=s[i]-'a'; if(!ch[u][c]) { memset(ch[sz],0,sizeof(ch[sz])); ch[u][c]=sz++; } u=ch[u][c]; sum[u]++; } pos[rank]=u; } void get_Fail() { int front=1,rear=1; //a pos for 0 f[0]=1; q[0]=1; for(int i=0,p;i<26;i++) if(p=ch[0][i]) f[p]=0,q[rear++]=p; while(front!=rear) { int qr=q[front++]; for(int c=0;c<26;c++) { int u=ch[qr][c]; if(!u) continue; q[rear++]=u; int v=f[qr]; while(v&&!ch[v][c]) v=f[v]; f[u]=ch[v][c]; } } for(int i=rear-1;i>=0;i--) sum[f[q[i]]]+=sum[q[i]]; } }ac; int n; char s ; int main() { scanf("%d",&n); ac.init(); for(int i=1;i<=n;i++) { scanf("%s",s); ac.insert(s,i); } ac.get_Fail(); for(int i=1;i<=n;i++) printf("%d\n",ac.sum[ac.pos[i]]); return 0; }
相关文章推荐
- 人工智能和机器学习领域的一些有趣的开源项目
- HDU 3487 Play with Chain
- 趣说游戏AI开发:曼哈顿街角的A*算法
- AIDL简单使用(通过它跨应用传递对象(数据))
- arch/arm/lib/crt0.S main主函数
- codeforces 630A Again Twenty Five!
- leetcode:Contains Duplicate II
- Install ncurses(ncurses-devel) and try again问题
- Zhi-Hua Zhou点评AI领域会议
- HDU 1151 Air Raid 二分图最小边覆盖
- if __name__ == '__main__':
- Error: linker command failed with exit code 1 (use -v to see invocation)
- OC中的关键字,weak,assign,copy,strong,nonatomic,retain
- scrapy爬虫之错误 No module named PIL + IOError:decoder jpeg not available +PIL的安装
- container_of(ptr, type, member)
- [Leetcode]-containsNearbyDuplicate
- Failure [INSTALL_FAILED_ALREADY_EXISTS]
- 【Linux运维入门】MongoDb启动报错:ERROR: child process failed, exited with error number xx
- Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE
- 【HDOJ】4363 Draw and paint