【题目链接】

  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+; struct ACauto {
int sz,ch[N][],sum[N],q[N],pos[N],f[N];
void init() {
sz=;
memset(ch[],,sizeof(ch[]));
}
void insert(char* s,int rank) {
int u=;
for(int i=;s[i];i++) {
int c=s[i]-'a';
if(!ch[u][c]) {
memset(ch[sz],,sizeof(ch[sz]));
ch[u][c]=sz++;
}
u=ch[u][c];
sum[u]++;
}
pos[rank]=u;
}
void get_Fail() {
int front=,rear=; //a pos for 0
f[]=; q[]=;
for(int i=,p;i<;i++)
if(p=ch[][i]) f[p]=,q[rear++]=p;
while(front!=rear) {
int qr=q[front++];
for(int c=;c<;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-;i>=;i--)
sum[f[q[i]]]+=sum[q[i]];
}
}ac; int n;
char s[N]; int main() {
scanf("%d",&n);
ac.init();
for(int i=;i<=n;i++) {
scanf("%s",s);
ac.insert(s,i);
}
ac.get_Fail();
for(int i=;i<=n;i++)
printf("%d\n",ac.sum[ac.pos[i]]);
return ;
}

bzoj 3172 [Tjoi2013]单词(fail树,DP)的更多相关文章

  1. bzoj 3172: [Tjoi2013]单词 fail树

    题目大意: 一篇论文是由许多单词组成,现在想知道每个单词分别在论文中出现多少次. 题解: 我们首先考虑fail指针的含义 如果fail[x] = y,那么我们就知道y作为x的后缀在x中出现了一次 所以 ...

  2. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

  3. BZOJ 3172([Tjoi2013]单词-后缀数组第一题+RMQ)

    3172: [Tjoi2013]单词 Time Limit: 10 Sec   Memory Limit: 512 MB Submit: 268   Solved: 145 [ Submit][ St ...

  4. bzoj 3172: [Tjoi2013]单词 AC自动机

    3172: [Tjoi2013]单词 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  5. BZOJ 3172 [Tjoi2013]单词 AC自己主动机(fail树)

    题意:链接 方法:AC自己主动机与fail树性质 解析:复习AC自己主动机的第一道题?(真正的第一题明明是又一次写了遍hdu2222! ) 这题说实话第一眼看上去就是个sb题,仅仅要建出来自己主动机. ...

  6. [BZOJ 3172] [Tjoi2013] 单词 【AC自动机】

    题目链接:BZOJ - 3172 题目分析: 题目要求求出每个单词出现的次数,如果把每个单词都在AC自动机里直接跑一遍,复杂度会很高. 这里使用AC自动机的“副产品”——Fail树,Fail树的一个性 ...

  7. BZOJ 3172 [Tjoi2013]单词 AC自动机Fail树

    题目链接:[http://www.lydsy.com/JudgeOnline/problem.php?id=3172] 题意:给出一个文章的所有单词,然后找出每个单词在文章中出现的次数,单词用标点符号 ...

  8. ●BZOJ 3172 [Tjoi2013]单词

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3172 题解: 把单词逐个接起来,中间用互不相同的字符连接,并记录下每个单词的首字母在串中的位 ...

  9. 【刷题】BZOJ 3172 [Tjoi2013]单词

    Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N ...

随机推荐

  1. li样式不显示使用overflow:hidden导致Li前面点、圈等样式不见

    点评:用了overflow:hidden 会影响 list-style,即当ul 中的li 的overflow 为hidden的时候,list-style不起作用,不显示前面的点.圈等样式,在ul或l ...

  2. CentOS 6.5升级Python后yum不可用的解决方案

    因开发需要,今天把CentOS 6.5自带的Python2.6.6升级到了Python2.7.3.按照如下步骤进行升级 1.查看当前系统python的版本 python -V 2.下载2.7.3版本的 ...

  3. 干货:Web应用上线之前程序员应该了解的技术细节

    [伯乐在线注]:<Web 应用上线前,程序员应考虑哪些技术细节呢?>这是 StackExchange 上面的一个经典问题贴. 最赞回复有 2200+ 顶,虽然大多数人可能都听过其中大部分内 ...

  4. 【Ubuntu12.04】安装搜狗输入法

    我的系统版本是Ubuntu12.04 32位 卸载Ibus输入法 sudo apt-get remove ibus 注意: 安装ibus的命令是  sudo apt-get install fcitx ...

  5. 【WPF】路由事件

    总结WPF中的路由事件,我将学到的内容分为四部分来逐渐掌握 第一部分:wpf中内置的路由事件 以Button的Click事件来说明内置路由事件的使用 XAML代码: <Window x:Clas ...

  6. App新版本提醒

    童鞋们是否遇过在使用app的时候出现有新版本更新跳转到苹果商店的提示呢? github中有一个三方框架 Harpy 完美实现了这一功能! demo时刻 我的github - Harpy

  7. java单例模式使用及注意事项

    1. 说明 1)单例模式:确保一个类只有一个实例,自行实例化并向系统提供这个实例 2)单例模式分类:饿单例模式(类加载时实例化一个对象给自己的引用),懒单例模式(调用取得实例的方法如getInstan ...

  8. Hadoop集群系类文章

    http://www.cnblogs.com/xia520pi/archive/2012/04/08/2437875.html 后续文章地址:http://www.xiapistudio.com/ta ...

  9. 剖析 Linux hypervisor--KVM 和 Lguest 简介

    慢慢弄清楚..   M. Tim Jones, 顾问工程师, Emulex Corp. M. Tim Jones 是一名嵌入式软件工程师,他是 Artificial Intelligence: A S ...

  10. C语言考试第一题详细过程

    1.计算 ,并输出其结果. 思路是先设计一个函数计算阶乘,再用循环,逐个求和. #include<stdio.h> int mul(int n) { int num,i; num=; ;i ...