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自动机俩模板的更多相关文章

  1. AC自动机 (模板)

    AC自动机是用来干什么的: AC自动机是用来解决多模匹配问题,例如有单词s1,s2,s3,s4,s5,s6,问:在文本串ss中有几个单词出现过,类似. AC自动机实现这个功能需要三个部分: 1.将所有 ...

  2. [hdu2222]ac自动机(模板)

    题意:一个文本串+多个模板串的匹配问题 思路:裸的ac自动机. #pragma comment(linker, "/STACK:10240000,10240000") #inclu ...

  3. HDOJ-3065(AC自动机+每个模板串的出现次数)

    病毒侵袭持续中 HDOJ-3065 第一个需要注意的是树节点的个数也就是tree的第一维需要的空间是多少:模板串的个数*最长模板串的长度 一开始我的答案总时WA,原因是我的方法一开始不是这样做的,我是 ...

  4. luogu AC自动机(模板)

    完全忘了AC自动机怎么写了qwq,更别说AC自动机上DP了. 今天就好好地学习字符串好了qwq 提一下AC自动机的时间复杂度--设n是模式串的个数,m是文本串的长度,l是模式串的平均长度,那么它的时间 ...

  5. AC自动机(模板) LUOGU P3808

    传送门 解题思路 AC自动机,是解决多模匹配问题的算法,是字典树与kmp结合的算法,可以解决许多子串在文本串中出现的次数等信息.关键是实现一个fail指针,是指向更靠上的前缀相同字母,从而可以实现在文 ...

  6. AC自动机(模板+例题)

    首先要明白AC自动机是干什么的: AC自动机其实就是一种多模匹配算法,那么你可能会问什么叫做多模匹配算法.下面是我对多模匹配的理解,与多模与之对于的是单模,单模就是给你一个单词,然后给你一个字符串,问 ...

  7. AC自动机及其模板

    模板 #include<queue> #include<stdio.h> #include<string.h> using namespace std; ; ; ; ...

  8. AC自动机(模板)

    #include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> ...

  9. hdu 2222 ac自动机更新模板 for onSite contest

    http://acm.split.hdu.edu.cn/showproblem.php?pid=2222 #include <cstdio> #include <cstdlib> ...

随机推荐

  1. Linux-Rsync命令参数详解

    在对rsync服务器配置结束以后,下一步就需要在客户端发出rsync命令来实现将服务器端的文件备份到客户端来.rsync是一个功能非常强大的工具,其命令也有很多功能特色选项,我们下面就对它的选项一一进 ...

  2. 使用JQuery,动态增加列

    这也是我在自己学做网站时无意搞出来的,希望可以对别人有所启发 <%@ page language="java" import="java.util.*" ...

  3. ATL com的dll文件与tlb文件

    一..tlb文件: 只有COM组件才有tlb文件,普通dll文件没有. 包含内容: 1.它包含了COM类和接口的GUID值,接口的函数声明信息,并不是接口的实现文件.相当于类和接口的头文件. tlb文 ...

  4. 通过Jquery异步获取股票实时数据

    最近朋友让我帮他做个异步获取数据的程序,暂时服务器什么都没有,所以我就想先拿股票数据打个框架,方便后续开发和移植等事情 代码如下: <!-- 说明:股票看盘 作者:黑桃A 时间:2014-04- ...

  5. 寻找总和为n的连续子数列之算法分析

    看到有这么道算法题在博客园讨论,算法eaglet和邀月都已经设计出来了,花了点时间读了下,学到点东西顺便记录下来吧. 题目是从1...n的数列中,找出总和为n的连续子数列. 这里先设好算法中需要用到的 ...

  6. BZOJ1707:[Usaco2007 Nov]tanning分配防晒霜

    我对贪心的理解:https://www.cnblogs.com/AKMer/p/9776293.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...

  7. python中http的一些编码转换

    http的数据需要2种编码解码. 1. url中的特殊字符转换, 比如",', :,//等 python3中通过urllib.parse.quote(..)和urllib.parse.unq ...

  8. virtual judge(专题一 简单搜索 E)

    Description Given a positive integer n, write a program to find out a nonzero multiple m of n whose ...

  9. spring扩展点之二:spring中关于bean初始化、销毁等使用汇总,ApplicationContextAware将ApplicationContext注入

    <spring扩展点之二:spring中关于bean初始化.销毁等使用汇总,ApplicationContextAware将ApplicationContext注入> <spring ...

  10. Unreal引擎术语表

    转自:http://www.cnblogs.com/hmxp8/archive/2012/02/10/2345274.html Unreal引擎术语表 转载自UDN: ‍Actor - 一个可以放置在 ...