ac自动机俩模板
ac自动机算法正确性还没有理解,算法导论也看不懂。。等懂了回来发算法专题。
#include <cstdio>
#include <cstring>
using namespace std; const int maxn=1e6+; int n;
char s[maxn]; class AC{
public:
struct node{
node *son[], *fail;
int mark;
}root, *now, *nowson, *p;
AC(){}
void insert(char *s, int len){ //trie,没什么好说的
now=&root;
int v;
for (int i=; i<len; ++i){
v=s[i]-'a';
if (!now->son[v]) now->son[v]=new node();
now=now->son[v];
}
++now->mark;
}
void get_fail(){ //建立失败指针
int head=, tail=;
q[head]=&root;
while (head<tail){ //宽搜
now=q[head];
for (int i=; i<; ++i) //遍历每个儿子
if (now->son[i]){
for (p=now->fail; p&&!p->son[i]; p=p->fail); //通过父亲来找失败指针
//p是0,意味着连root都不行,那只能去root
now->son[i]->fail=(p?p->son[i]:&root);
q[tail++]=now->son[i];
} //else now->son[i]=now->fail->son[i]; //如果没有这个子节点,意味着肯定失配
++head;
}
}
int count(char *s, int len){ //计算有多少个串出现
int ans=;
now=&root;
int v;
for (int i=; i<len; ++i){
//确定适配的树的结点位置
for (v=s[i]-'a'; now&&!now->son[v]; now=now->fail);
now=now?now->son[v]:&root; //如果一直到根还不匹配,那就跳到根
//对于一个匹配串的所有后缀检查
//如果这里ans没设置为-1,那就是求出现次数之和
for (p=now; p&&~p->mark; p=p->fail) {
ans+=p->mark;
p->mark=-;
}
}
return ans;
}
private:
node *q[maxn], head, tail;
}; AC ac; int main(){
scanf("%d", &n);
for (int i=; i<n; ++i){
scanf("%s", s);
int t=strlen(s);
ac.insert(s, t);
}
ac.get_fail();
scanf("%s", s);
printf("%d\n", ac.count(s, strlen(s)));
return ;
}
#include <cstdio>
#include <cstring>
using namespace std; const int maxn=, maxl1=, maxl2=1e6+; int n, cnt, ans[maxn];
char p[maxn][maxl1];
char t[maxl2]; struct node{
node *son[], *fail;
int id, mark;
}*mem[maxn*maxl1];
class AC{
public:
node *root, *now, *nowson, *p;
AC(){ root=new node(); }
void fresh(){
cnt=;
delete root;
root=new node();
for (int i=; i<memlen; ++i) delete mem[i];
memlen=;
}
void insert(char *s, int len){ //trie,没什么好说的
now=root;
int v;
for (int i=; i<len; ++i){
v=s[i]-'a';
if (!now->son[v]) {
now->son[v]=new node();
mem[memlen++]=now->son[v];//内存回收表
}
now=now->son[v];
}
//如果不去重,这里写成等于1
now->id=cnt++;
++now->mark;
}
void get_fail(){ //建立失败指针
int head=, tail=;
q[head]=root;
while (head<tail){ //宽搜
now=q[head];
for (int i=; i<; ++i) //遍历每个儿子
if (now->son[i]){
for (p=now->fail; p&&!p->son[i]; p=p->fail); //通过父亲来找失败指针
//p是0,意味着连root都不行,那只能去root
now->son[i]->fail=(p?p->son[i]:root);
q[tail++]=now->son[i];
} //else now->son[i]=now->fail->son[i]; //如果没有这个子节点,意味着肯定失配
++head;
}
}
void count(char *s, int len){ //计算有多少个串出现
now=root;
int v;
for (int i=; i<len; ++i){
//确定适配的树的结点位置
for (v=s[i]-'a'; now&&!now->son[v]; now=now->fail);
now=now?now->son[v]:root; //如果一直到根还不匹配,那就跳到根
//对于一个匹配串的所有后缀检查
//如果这里ans没设置为-1,那就是求出现次数之和
for (p=now; p&&~p->mark; p=p->fail) {
ans[p->id]+=p->mark;
//p->mark=-1;
}
}
}
private:
node *q[maxn*maxl1]; //这里忘记加了
int memlen;
}; AC ac; int main(){
scanf("%d", &n);
while (n){
memset(ans, , sizeof(ans));
for (int i=; i<n; ++i){
scanf("%s", p[i]);
int t=strlen(p[i]);
ac.insert(p[i], t);
}
ac.get_fail();
scanf("%s", t);
ac.count(t, strlen(t));
int maxm=;
for (int i=; i<n; ++i)
if (ans[i]>maxm) maxm=ans[i];
printf("%d\n", maxm);
for (int i=; i<n; ++i)
if (ans[i]==maxm) printf("%s\n", p[i]);
scanf("%d", &n);
ac.fresh();
}
return ;
}
ac自动机俩模板的更多相关文章
- AC自动机 (模板)
AC自动机是用来干什么的: AC自动机是用来解决多模匹配问题,例如有单词s1,s2,s3,s4,s5,s6,问:在文本串ss中有几个单词出现过,类似. AC自动机实现这个功能需要三个部分: 1.将所有 ...
- [hdu2222]ac自动机(模板)
题意:一个文本串+多个模板串的匹配问题 思路:裸的ac自动机. #pragma comment(linker, "/STACK:10240000,10240000") #inclu ...
- HDOJ-3065(AC自动机+每个模板串的出现次数)
病毒侵袭持续中 HDOJ-3065 第一个需要注意的是树节点的个数也就是tree的第一维需要的空间是多少:模板串的个数*最长模板串的长度 一开始我的答案总时WA,原因是我的方法一开始不是这样做的,我是 ...
- luogu AC自动机(模板)
完全忘了AC自动机怎么写了qwq,更别说AC自动机上DP了. 今天就好好地学习字符串好了qwq 提一下AC自动机的时间复杂度--设n是模式串的个数,m是文本串的长度,l是模式串的平均长度,那么它的时间 ...
- AC自动机(模板) LUOGU P3808
传送门 解题思路 AC自动机,是解决多模匹配问题的算法,是字典树与kmp结合的算法,可以解决许多子串在文本串中出现的次数等信息.关键是实现一个fail指针,是指向更靠上的前缀相同字母,从而可以实现在文 ...
- AC自动机(模板+例题)
首先要明白AC自动机是干什么的: AC自动机其实就是一种多模匹配算法,那么你可能会问什么叫做多模匹配算法.下面是我对多模匹配的理解,与多模与之对于的是单模,单模就是给你一个单词,然后给你一个字符串,问 ...
- AC自动机及其模板
模板 #include<queue> #include<stdio.h> #include<string.h> using namespace std; ; ; ; ...
- AC自动机(模板)
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> ...
- hdu 2222 ac自动机更新模板 for onSite contest
http://acm.split.hdu.edu.cn/showproblem.php?pid=2222 #include <cstdio> #include <cstdlib> ...
随机推荐
- Tomcat启动分析(我们为什么要配置CATALINA_HOME环境变量)
原文:http://www.cnblogs.com/heshan664754022/archive/2013/03/27/2984357.html Tomcat启动分析(我们为什么要配置CATALIN ...
- 数据库中的id不会自动 替换,这个应该处理吗。怎么处理,那个是唯一主键
- codeforces 655B B. Mischievous Mess Makers(贪心)
题目链接: B. Mischievous Mess Makers time limit per test 1 second memory limit per test 256 megabytes in ...
- linux命令学习笔记(9):touch 命令
linux的touch命令不常用,一般在使用make的时候可能会用到,用来修改文件时间戳,或者新建一个不存在的文件. .命令格式: touch [选项]... 文件... .命令参数: -a 或--t ...
- 【leetcode刷题笔记】Remove Nth Node From End of List
Given a linked list, remove the nth node from the end of list and return its head. For example, Give ...
- ACM学习历程—CSU 1216 异或最大值(xor && 贪心 && 字典树)
题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1216 题目大意是给了n个数,然后取出两个数,使得xor值最大. 首先暴力枚举是C(n, ...
- uoj problem 10
uoj problem 10 题目大意: 给定任务若干,每个任务在\(t_i\)收到,需要\(s_i\)秒去完成,优先级为\(p_i\) 你采用如下策略: 每一秒开始时,先收到所有在该秒出现的任务,然 ...
- npm in macbook
打开终端,试了很多次 npm install anywhere -g,结果还是报错,大概就说没权限. 所以,才想起之前看过的博客中,提到用sudo去执行. 终于,没问题了! 如果npm install ...
- js一个游戏小笔记
昨天写了个飞机大战的游戏,没弄好的一点是如何移动炮台. 开始我把移动代码写到了炮台类里面,但是怎么按都不移动.(最烦,代码对,效果不对,╮(╯▽╰)╭) 问过老师才知道,这种移动类游戏,应该把 控制 ...
- glusterfs安装配置简单使用
GlusterFS是一种分布式分布式文件系统,默认采用无中心完全对等架构,搭建维护使用十分简单,是很受欢迎的分布式文件系统. 官网https://www.gluster.org/,官网上表示Glust ...