题目:P3808:https://www.luogu.org/problemnew/show/P3808

P3796:https://www.luogu.org/problemnew/show/P3796

从这里学了下AC自动机:http://www.cnblogs.com/cjyyb/p/7196308.html

我的理解大概就是构建一棵由模式串组成的 Trie 树,然后把文本串一节一节放在上面查找;

失配指针指向的是结尾字母和自己一样的、Trie 树上的其他分支,大约就是在找后缀这样的感觉;

所以文本串每加入一个字符,就在 Trie 树上查找以这个字符结尾的后缀模式串,所以能找到所有出现过的;

慕名已久的AC自动机原来也挺简单的嘛!

代码如下:

P3808:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int const maxn=1e6+;
int n,cnt;
queue<int>q;
struct N{
int fail,son[],end;
}AC[maxn];
void build(string s)
{
int l=s.length();
int nw=;
for(int i=;i<l;i++)
{
if(AC[nw].son[s[i]-'a']==)AC[nw].son[s[i]-'a']=++cnt;
nw=AC[nw].son[s[i]-'a'];
}
AC[nw].end++;
}
void get_fail()
{
AC[].fail=;
for(int i=;i<;i++)
{
if(AC[].son[i]==)continue;
AC[AC[].son[i]].fail=;
q.push(AC[].son[i]);
}
while(q.size())
{
int x=q.front(); q.pop();
for(int i=;i<;i++)
{
if(AC[x].son[i])
{
AC[AC[x].son[i]].fail=AC[AC[x].fail].son[i];
q.push(AC[x].son[i]);
}
else AC[x].son[i]=AC[AC[x].fail].son[i];
}
}
}
int query(string s)
{
int l=s.length();
int ret=,nw=;
for(int i=;i<l;i++)
{
nw=AC[nw].son[s[i]-'a'];
for(int t=nw;t&&AC[t].end!=-;t=AC[t].fail)
{
ret+=AC[t].end;
AC[t].end=-;
}
}
return ret;
}
int main()
{
scanf("%d",&n);
string s;
for(int i=;i<=n;i++)
{
cin>>s;
build(s);
}
get_fail();
cin>>s;
printf("%d\n",query(s));
return ;
}

P3796:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int const maxn=1e6+;
int n,cnt;
queue<int>q;
string s[];
struct N{
int son[],fail,end;
}AC[maxn];
struct P{int num,pos;}ans[];
bool cmp(P x,P y)
{
if(x.num==y.num)return x.pos<y.pos;
else return x.num>y.num;
}
void clear(int x)
{
memset(AC[x].son,,sizeof AC[x].son);
AC[x].fail=; AC[x].end=;
}
void build(string s,int num)
{
int l=s.length();
int nw=;
for(int i=;i<l;i++)
{
if(!AC[nw].son[s[i]-'a'])AC[nw].son[s[i]-'a']=++cnt,clear(cnt);
nw=AC[nw].son[s[i]-'a'];
}
AC[nw].end=num;
}
void get_fail()
{
while(q.size())q.pop();
AC[].fail=;
for(int i=;i<;i++)
{
if(AC[].son[i]==)continue;
AC[AC[].son[i]].fail=; q.push(AC[].son[i]);
}
while(q.size())
{
int x=q.front(); q.pop();
for(int i=;i<;i++)
{
if(AC[x].son[i])
{
AC[AC[x].son[i]].fail=AC[AC[x].fail].son[i];
q.push(AC[x].son[i]);
}
else AC[x].son[i]=AC[AC[x].fail].son[i];
}
}
}
void query(string s)
{
int l=s.length();
int nw=;
for(int i=;i<l;i++)
{
nw=AC[nw].son[s[i]-'a'];
for(int t=nw;t/*&&t.end!=-1*/;t=AC[t].fail)
{
ans[AC[t].end].num++;
// AC[t].end=-1;
}
}
}
int main()
{
while()
{
scanf("%d",&n);
if(!n)return ;
cnt=; clear();
for(int i=;i<=n;i++)
{
cin>>s[i];
build(s[i],i);
ans[i].pos=i;
ans[i].num=;//
}
get_fail();
cin>>s[];
query(s[]);
sort(ans+,ans+n+,cmp);
printf("%d\n",ans[].num);
cout<<s[ans[].pos]<<endl;
for(int i=;i<=n;i++)
{
if(ans[i].num==ans[i-].num)
cout<<s[ans[i].pos]<<endl;
else break;
}
}
}

洛谷P3808 & P3796 AC自动机模板的更多相关文章

  1. 洛谷 - P3966 - 单词 - AC自动机

    https://www.luogu.org/problemnew/show/P3966 因为文本串就是字典本身,所以这个和平时的AC自动机不太一样.平时的query要沿着fail树把子树的出现次数依次 ...

  2. 洛谷.3121.审查(AC自动机 链表)

    题目链接 //删掉一个单词需要前移一段位置,用链表维护就好了 复杂度O(sum(len)) #include <cstdio> #include <cstring> #defi ...

  3. 洛谷 - P2444 - 病毒 - AC自动机

    https://www.luogu.org/problemnew/show/P2444 有点恶心,不太明白fail的意义. #include<bits/stdc++.h> using na ...

  4. 洛谷P3808 【模板】AC自动机(简单版)

    题目背景 这是一道简单的AC自动机模板题. 用于检测正确性以及算法常数. 为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交. 管理员提示:本题数据内有重复的单词,且重复单词应该计算多次, ...

  5. 【刷题】洛谷 P3808 【模板】AC自动机(简单版)

    题目背景 这是一道简单的AC自动机模板题. 用于检测正确性以及算法常数. 为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交. 管理员提示:本题数据内有重复的单词,且重复单词应该计算多次, ...

  6. 浅谈AC自动机模板

    什么是AC自动机? 百度百科 Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法. 要学会AC自动机,我们必须知道什么是Trie,也就是字典树.Tr ...

  7. (模板)AC自动机模板

    模板1. 给出模式串和文本串,文本串长度小于1e6,模式串长度之和小于1e6,求文本串中有多少模式串出现. 题目链接:https://www.luogu.org/problem/P3808 AC co ...

  8. HDU 2222 AC自动机模板题

    题目: http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机模板题 我现在对AC自动机的理解还一般,就贴一下我参考学习的两篇博客的链接: http: ...

  9. Match:Keywords Search(AC自动机模板)(HDU 2222)

    多模匹配 题目大意:给定很多个字串A,B,C,D,E....,然后再给你目标串str字串,看目标串中出现多少个给定的字串. 经典AC自动机模板题,不多说. #include <iostream& ...

随机推荐

  1. redis集群——RPLR简笔(Redis+PostgreSQL+Linux(centos7)+RabbitMQ)

    使用的是centos7. 1.下载最新redis源码,解压(2016-05-12最新版本为3.2.0,3.0及以上才有官方集群) 2.进入源码根目录(此目录下的redis-stable目录),找到ut ...

  2. Ajax——php基础知识(三)

    上传文件 1.get是传不了文件的,只能用post 2.enctype需要重新设置,默认是application/x-www-form-urlencoded,会在发送到服务器之前,所有字符都会进行编码 ...

  3. jQuery——jQuery选择器

    基本选择器 # Id选择器 $(“#btnShow”)选择id为btnShow的一个元素 . 类选择器 $(“.liItem”)选择含有类liItem的所有元素 ele 标签选择器 $(“li”)选择 ...

  4. SQL基本操作——DROP撤销索引、表以及数据库

    DROP撤销索引.表以及数据库 --DROP INDEX 命令删除表格中的索引 DROP INDEX table_name.index_name --DROP TABLE 语句删除表(表的结构.属性以 ...

  5. Lazarus Coolbar and AnchroDocking

    在lazarus1.6里加载了AnchroDocking后,Coolbar突然不见了,找了好久没找到,原来在这里! 在AnchroDocking中可能是为了界面的最大化,默认是开始Toolbar 而关 ...

  6. NSOperationQueue和GCD的区别,以及在什么场合下使用

    1> GCD是纯C语言的API .NSOperationQueue是基于GCD的OC的封装. 2> GCD只支持FIFO队列,NSOperationQueue可以方便设置执行顺序,设置最大 ...

  7. js 闭包 定时器

    ; !function (win) { ; //内部私有 , ; //内部私有 //test.prototype.tt1 = 0;//共有变量 var test = function () {}; t ...

  8. js 不能用关键字 delete 做函数名

    把delete更改为mydelete正常.

  9. vino-server服务是啥服务

    近期接手一个项目,开始梳理服务器,突然发现有个进程是开启5900远程桌面端口的, 在不知情的情况下怕被人给利用了,啥也不说,先干掉再说. server端开启vino-server,允许别人查看自己的桌 ...

  10. Opencv学习之路—Opencv下基于HOG特征的KNN算法分类训练

    在计算机视觉研究当中,HOG算法和LBP算法算是基础算法,但是却十分重要.后期很多图像特征提取的算法都是基于HOG和LBP,所以了解和掌握HOG,是学习计算机视觉的前提和基础. HOG算法的原理很多资 ...