AC自动机 数组实现
AC自动机的实现原理是KMP + 字典树。 学AC自动机之前要先去学KMP 和 字典树。
第一步先构建一个字典树。
void Insert(){
int rt = , len = strlen(str);
for(int i = ; i < len; i++){
int id = str[i] - 'a';
if(trie[rt][id] == ){
cnt[tot] = ;
fair[tot] = ;
trie[rt][id] = tot++;
}
rt = trie[rt][id];
}
cnt[rt]++;
}
插入字典树
第二步 通过BFS来构造fair指针。
void Build_tree(){
queue<int> q;
q.push();
int p;
while(!q.empty()){
int tmp = q.front();
q.pop();
for(int i = ; i < ; i++){
if(trie[tmp][i] != ){
if(tmp == )
fair[trie[tmp][i]] = ;
else{
p = fair[tmp];
while(p){
if(trie[p][i]){
fair[trie[tmp][i]] = trie[p][i];
break;
}
else p = fair[p];
}
if(!p) fair[trie[tmp][i]] = ;
}
q.push(trie[tmp][i]);
}
}
}
}
构造fair指针
第三步 进行匹配。
统计有多少个单词的出现过。
int Query(){
int rt = , ret = , len = strlen(str);
for(int i = ; i < len; i++){
int id = str[i] - 'a';
while(!trie[rt][id] && rt != ) rt = fair[rt];
rt = trie[rt][id];
if(rt == ) rt = ;
int tmp = rt;
while(tmp != ){
if(cnt[tmp] >= ){
ret += cnt[tmp];
cnt[tmp] = -;
}
else break;
tmp = fair[tmp];
}
}
return ret;
}
统计单词个数。
AC自动机 模板题 HDU-2222 Keywords Search
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
const int INF = 0x3f3f3f3f;
const LL mod = 1e9+;
typedef pair<int,int> pll;
const int N = 1e5+, M = 1e3;
char str[N*];
int trie[N*][];
int fair[N*];
int cnt[N*];
int tot = ;
void Insert(){
int rt = , len = strlen(str);
for(int i = ; i < len; i++){
int id = str[i] - 'a';
if(trie[rt][id] == ){
cnt[tot] = ;
fair[tot] = ;
trie[rt][id] = tot++;
}
rt = trie[rt][id];
}
cnt[rt]++;
}
void Build_tree(){
queue<int> q;
q.push();
int p;
while(!q.empty()){
int tmp = q.front();
q.pop();
for(int i = ; i < ; i++){
if(trie[tmp][i] != ){
if(tmp == )
fair[trie[tmp][i]] = ;
else{
p = fair[tmp];
while(p){
if(trie[p][i]){
fair[trie[tmp][i]] = trie[p][i];
break;
}
else p = fair[p];
}
if(!p) fair[trie[tmp][i]] = ;
}
q.push(trie[tmp][i]);
}
}
}
}
int Query(){
int rt = , ret = , len = strlen(str);
for(int i = ; i < len; i++){
int id = str[i] - 'a';
while(!trie[rt][id] && rt != ) rt = fair[rt];
rt = trie[rt][id];
if(rt == ) rt = ;
int tmp = rt;
while(tmp != ){
if(cnt[tmp] >= ){
ret += cnt[tmp];
cnt[tmp] = -;
}
else break;
tmp = fair[tmp];
}
}
return ret;
}
void init(){
for(int i = ; i < tot; i++){
for(int j = ; j < ; j++)
trie[i][j] = ;
}
tot = ;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
init();
int n;
scanf("%d", &n);
while(n--){
scanf("%s", str);
Insert();
}
Build_tree();
scanf("%s", str);
printf("%d\n", Query());
}
return ;
}
HDU-2222
AC自动机 数组实现的更多相关文章
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序
3881: [Coci2015]Divljak Time Limit: 20 Sec Memory Limit: 768 MBSubmit: 508 Solved: 158[Submit][Sta ...
- bzoj 3172 单词 ac自动机|后缀数组
题目大意: 给定n个字符串连成了一篇文章,问每个字符串在这篇文章中出现的次数,可重复覆盖 这里ac自动机和后缀数组都可以做 当然后缀数组很容易就解决,但是相对时间消耗高 这里就只讲ac自动机了 将每个 ...
- bzoj 3172 后缀数组|AC自动机
后缀数组或者AC自动机都可以,模板题. /************************************************************** Problem: 3172 Us ...
- 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2022 Solved: 1158[Submit][Sta ...
- 中文分词系列(二) 基于双数组Tire树的AC自动机
秉着能偷懒就偷懒的精神,关于AC自动机本来不想看的,但是HanLp的源码中用户自定义词典的识别是用的AC自动机实现的.唉-没办法,还是看看吧 AC自动机理论 Aho Corasick自动机,简称AC自 ...
- CF 163E. e-Government ac自动机+fail树+树状数组
E. e-Government 题目: 给出n个字符串,表示n个人名,有两种操作: ?string ,统计字符串string中出现的属于城市居民的次数. +id,把编号为id的人变为城市居民,如果已经 ...
- BZOJ_2434_[NOI2011]_阿狸的打字机_(AC自动机+dfs序+树状数组)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2434 给出\(n\)个字符串,\(m\)个询问,对于第\(i\)个询问,求第\(x_i\)个字 ...
- tyvj P1519 博彩游戏(AC自动机+DP滚动数组)
P1519 博彩游戏 背景 Bob最近迷上了一个博彩游戏…… 描述 这个游戏的规则是这样的:每花一块钱可以得到一个随机数R,花上N块钱就可以得到一个随机序列:有M个序列,如果某个序列是产生的随机序列的 ...
随机推荐
- python 实现爬取网站下所有URL
python3 实现爬取网站下所有URL 获取首页元素信息: 首页的URL链接获取: 遍历第一次返回的结果: 递归循环遍历: 全部代码如下: 小结: python3.6 requests && ...
- 使用ForkJoinPool来多线程的拆分任务,执行任务,合并结果。
ForkJoinPool 是jdk1.7 由Doug Lea 写的实现 递归调用任务拆分,合并,的线程池. 代码示例: package www.itbac.com; import com.alib ...
- 用泛型写Redis缓存与数据库操作工具类
功能描述: 先从缓存获取数据,如果缓存没有,就从数据库获取数据,并设置到缓存中,返回数据. 如果数据库中没有数据,需要设置一个缓存标记flagKey,防止暴击访问数据库,用缓存保护数据库. 当删除缓存 ...
- java8中用流收集数据
用流收集数据 汇总 long howManyDishes = menu.stream().collect(Collectors.counting()); int totalCalories = men ...
- 【一些小常识】Linux文件目录的通配符用法/*
在使用linux命令的时候,一时有点搞不清*的用法,于是整理记录下,在做jenkins 持续集成时还是很有用的 “*”在通配符中是最常用的一种,主要整理下在使用Linux命令时,文件夹目录的用法. 1 ...
- 跟着大彬读源码 - Redis 9 - 对象编码之 三种list
目录 1 ziplist 2 skiplist 3 quicklist 总结 Redis 底层使用了 ziplist.skiplist 和 quicklist 三种 list 结构来实现相关对象.顾名 ...
- SpringBoot学习系列之一(反射)
最近在学习SpringBoot的知识,动起手来学习的时候才发现SpringBoot项目采用了大量的反射机制,晕,作为一个应届毕业生,以前学习反射的时候给我的感觉就是,这个到底用来干嘛的,好像没啥用啊, ...
- Flink 源码解析 —— 如何获取 ExecutionGraph ?
https://t.zsxq.com/UnA2jIi 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Mac 上搭建 Flink 1.6. ...
- Java虚拟机日志与参数
虚拟机日志 打印GC日志可以使用参数-XX:+PrintGC /** * -Xmx10m -Xms10m -XX:PretenureSizeThreshold=10485760 * -XX:+Prin ...
- Linux 目录递归赋权,解决 Linux权限不够
如你要操作一个目录下的文件时,系统提示 “权限不够”,可用以下方法解决. 如 test 文件目录. 1.用root账号登陆系统. 2.输入如下命令: chmod 777 test -R 这样访问.修改 ...