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. hdu 1503 Advanced Fruits(最长公共子序列)

    Advanced Fruits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  2. python_doc 读写docx文件

    python读写word文档有现成的库可以处理,在这里采用了 python-docx. 首先先安装 pip install python-docx #!/usr/bin/env python # -* ...

  3. 5 Python 数据类型—数字

    Python Number 数据类型用于存储数值. 数据类型是不允许改变的,这就意味着如果改变 Number 数据类型的值,将重新分配内存空间. var1 = 1 var2 = 10 您也可以使用de ...

  4. 【遍历二叉树】03二叉树的后序遍历【Binary Tree Postorder Traversal】

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个二叉树,返回他的后序遍历的 ...

  5. 用Word编辑cnblogs的博文并发布

    听说可以用Word直接编辑文件发布博客,请教加研究,终于配置成功,先分享如下: 1. 在www.cnblogs.com上注册用户. 2. 打开Word,选择博客文章 3. 点击管理账户,新建或更改,按 ...

  6. 问题6:如何让字典保持有序(使用collections的OrderedDict方法)

    from collections imort OrderedDict d = OrderedDict() d['aa'] = (1, 30) d['bb'] = (2, 31) d['cc'] = ( ...

  7. 【转】 Pro Android学习笔记(六八):HTTP服务(2):HTTP POST

    目录(?)[-] 找一个测试网站 HTTP POST小例子 上次学习了HTTP GET请求,这次学习一下HTTP POST. 找一个测试网站 小例子好写,但要找个测试网站就有些麻烦,一下子无从入手,都 ...

  8. fiddler 的AutoRespoder的使用(手动添加测试桩)

    ---恢复内容开始--- 1.首先我们抓取一个百度的请求,由于百度请求是https协议,需要手动添加证书(这个不写了,大佬们自己手动找下资料) 2.fiddler抓取的百度请求,其他的无关信息删除,便 ...

  9. 电脑当路由使用(目前只在win7上用过)

    前提:电脑有无线网卡,并打开了无线 第一步使用管理员权限运行cmd.exe 1.执行如下命令 netsh wlan set hostednetwork mode=allow ssid=myWifi k ...

  10. Python-Redis的Set操作

    集合为不重复的列表 无序集合 sadd(name,values):在name对应的集合中添加元素 smembers(name):获取name对应的集合的所有成员 127.0.0.1:6379> ...