题目大意:

给定n个字符串连成了一篇文章,问每个字符串在这篇文章中出现的次数,可重复覆盖

这里ac自动机和后缀数组都可以做

当然后缀数组很容易就解决,但是相对时间消耗高

这里就只讲ac自动机了

将每个字符串放入ac自动机中,这里需要记录到达每个ac自动机上的节点出现这个状态有多少次

而我们添加字符串进入的时候,应该是把经过的每个节点的val都++,说明这个字符串多出现了一次这个值

然后因为自己用字符串在ac自动机上走肯定是到达离root最近的点,也就是说有很多的点会不断通过fail指针指向他,而这些点都是包含了这个字符串的

那也就是说我们需要考虑 val[fail[i]] += val[i]

这里一定是需要从最底层的点不断fail上来,我们需要找到一个合适的更新val点的顺序

可以考虑在我们构建后缀自动机的时候我们采用的是利用队列bfs的过程,那也就是说进入的点是符合最大长度从小到大的性质的

而fail指向的总是比它长度更小的点,所以根据进入队列的点的逆顺序来更新val即可

也就是每次点进队列都 que[cnt++] = u;

最后

for(int i=sz-1 ; i>0 ; i--)
  val[fail[que[i]]]+=val[que[i]];

 #include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
#define clr(x) memset(x , 0 , sizeof(x))
#define set(x) memset(x , -1 , sizeof(x))
typedef long long LL ; const int CHAR_SIZE = ;
const int MAX_SIZE = ;
const int M = ; struct AC_Machine{
int ch[MAX_SIZE][CHAR_SIZE] , val[MAX_SIZE] , fail[MAX_SIZE] , que[MAX_SIZE];
int sz;
bool vis[MAX_SIZE];
void init(){
sz = ;
clr(ch[]) , clr(val) , clr(vis);
} int insert(string s){
int n = s.length();
int u= ;
for(int i= ; i<n ; i++){
int c = s[i]-'a';
if(!ch[u][c]){
clr(ch[sz]) , val[sz]=;
ch[u][c] = sz++;
}
u = ch[u][c];
val[u]++;
}
return u;
} void get_fail(){
queue<int> Q;
fail[] = ;
int cnt = ;
for(int c= ; c<CHAR_SIZE ; c++){
int u = ch[][c];
if(u){Q.push(u);fail[u]=,que[cnt++]=u;}
}
while(!Q.empty()){
int r = Q.front();
Q.pop();
for(int c= ; c<CHAR_SIZE ; c++){
int u = ch[r][c];
if(!u){ch[r][c] = ch[fail[r]][c]; continue;}
fail[u] = ch[fail[r]][c];
Q.push(u);
que[cnt++]=u;
}
}
}
void updateVal(){
for(int i=sz- ; i> ; i--)
val[fail[que[i]]]+=val[que[i]];
}
}ac;
int n , pos[];
string s[]; int main()
{
// freopen("a.in" , "r" , stdin);
// freopen("out.txt" , "w" , stdout);
scanf("%d" , &n);
ac.init();
for(int i= ; i<n ; i++){
cin>>s[i];
pos[i] = ac.insert(s[i]);
}
ac.get_fail();
ac.updateVal();
for(int i= ; i<n ; i++)
printf("%d\n" , ac.val[pos[i]]);
return ;
}

bzoj 3172 单词 ac自动机|后缀数组的更多相关文章

  1. 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机

    为何scanf("%s", str)不需要&运算 经常忘掉的字符串知识点,最好不加&,不加&最标准,指针如果像scanf里一样加&是错的,大概是未定 ...

  2. Trie树&kmp&AC自动机&后缀数组&Manacher

    Trie 计数+Trie,读清题意很重要 https://vjudge.net/problem/UVALive-5913 kmp AC自动机 模板:https://vjudge.net/problem ...

  3. (17/34)AC自动机/后缀数组/后缀自动机(施工中)

    快补题别再摸鱼了(17/34) 1.AC自动机 #define maxnode 1000010 #define maxsize 26 struct ahocT{ int ch[maxnode][max ...

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

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

  5. BZOJ 3172 单词(ac自动机)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3172 题意:给出n个单词.输出每个单词在所有单词中一共出现多少次? 思路:首先将所有单词 ...

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

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

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

    关于AC自动机:一个在kmp与Trie的基础上建立的数据结构,关键在于Trie树结构与fail指针,他们各有各的应用.在AC自动机里最典型的就是多串匹配,原本效率为O(n*l+n*l+m*l),(n是 ...

  8. BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树

    Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...

  9. bzoj 3796: Mushroom追妹纸 AC自动机+后缀自动机+dp

    题目大意: 给定三个字符串s1,s2,s3,求一个字符串w满足: w是s1的子串 w是s2的子串 s3不是w的子串 w的长度应尽可能大 题解: 首先我们可以用AC自动机找出s3在s1,s2中出现的位置 ...

随机推荐

  1. Entity Framework 数据库初始化四种策略

    策略一:数据库不存在时重新创建数据库 Database.SetInitializer<testContext>(new CreateDatabaseIfNotExists<testC ...

  2. Query Designer:Hierarchy层级显示

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  3. IIS设置session时长

    打开IIS管理器,选择要设置的session的网站,打开右边窗口的会话状态.选择状态服务器,设置连接字符串,并在服务管理开户状态服务 ASP.NET State Service

  4. HDU 5860 Death Sequence(死亡序列)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...

  5. latex给表格添加注释

    给表格加注释的确是很多TeX用户不好用的地方,这里提供一个样式和代码,或许对于你的学习使用有所帮助,样式如下: 代码如下: \documentclass[11pt,a4paper,english]{a ...

  6. Linux英文全称

    su:Swith user  切换用户,切换到root用户cat: Concatenate  串联uname: Unix name  系统名称df: Disk free  空余硬盘du: Disk u ...

  7. (转)Linux NFS服务器的安装与配置

    转自:http://www.cnblogs.com/mchina/archive/2013/01/03/2840040.html 由于在6系列里面,portmap已经改名了 ,6系列需要使用 serv ...

  8. Selenium:元素等待的4种方法

    1.使用Thread.sleep(),这是最笨的方法,但有时候也能用到而且很实用. 2.隐示等待,隐性等待是指当要查找元素,而这个元素没有马上出现时,告诉WebDriver查询Dom一定时间.默认值是 ...

  9. 用到的一些python包,记录下

    Requests beautifulsoup lxml logging gevent django Bottle numpy pandas sklearn pyopencv opencv_python ...

  10. 表单提交与后台PHP如何接口?

    在网页中,常常有这样那样的表单需要提交,比如登陆,比如注册,比如查询,比如填写问卷.在这样的表单提交过程中,我们究竟向后台提交了什么,是以什么形式提交的,是一个很值得探讨的问题. 提交了什么——就是我 ...