AC自动机这个算法网上有很多资料,这里就不多赘述了。

当从一个字符串中查找另一个字符串,我们有快速的算法KMP。

现在的问题是要从一个字符串中查找很多字符串,或者要从多个字符串里分别查找很多字符串。AC自动机就是解决这个问题的。

HDU2222的题意就是要从一个字符串中查找很多字符串,很裸的模板题。不过测试数据相当的水,有很多人错误的程序都AC掉了。

我们把一个字符串中查找很多字符串中的一个字符串成为文本串,很多字符串称为模式串。

AC自动机的算法步骤就是,先用模式串建立一颗字典树,再BFS出带fail指针的字典树,最后拿文本串在这棵字典树中跑就可以了。

一开始写了一发代码。

#include<bits/stdc++.h>
const int maxnode=26;
using namespace std;
struct node
{int sum;node *next[maxnode];node *fail;node(){memset(next,0,sizeof(next));sum=0;fail=NULL;}
};
node *root=new node();
void Insert(string s)
{node *p=root;for(int i=0;i<s.size();i++){int id=s[i]-'a';if(p->next[id]==NULL) p->next[id]=new node();p=p->next[id]; }p->sum++;
}
void Build()
{node *p=root;queue<node *>que;for(int i=0;i<maxnode;i++) {if(p->next[i]){p->next[i]->fail=root;que.push(p->next[i]);}else p->next[i]=root;}while(que.size()){p=que.front();que.pop();for(int i=0;i<maxnode;i++){if(p->next[i]) {p->next[i]->fail=p->fail->next[i];que.push(p->next[i]);}else p->next[i]=p->fail->next[i];}}
}
int Query(string s)
{int ans=0;queue<pair<node*,int> >status;node *p=root;for(int i=0;i<s.size();i++){int id=s[i]-'a';if(p->next[id]){p=p->next[id];node *tmp=p;while(tmp->sum){ans+=tmp->sum;status.push(make_pair(tmp,tmp->sum));tmp->sum=0;tmp=tmp->fail;}}}while(status.size()){pair<node*,int> tmp=status.front();status.pop();tmp.first->sum=tmp.second;}return ans;
}
int main()
{ios::sync_with_stdio(false);int t,n;string s;cin>>t;while(t--){cin>>n;for(int i=1;i<=n;i++){cin>>s;Insert(s);}Build();cin>>s;cout<<Query(s)<<endl;}return 0;
}

Memory Limit Exceeded到死。

调试了一下午才明白,这是多组数据,而我根没有初始化,这样就会导致,后面的数据是在原来的字典树上构造的,相当于数据都累加起来了。必然导致MLE。所以改了一下每次初始化根就好了。

#include<bits/stdc++.h>
const int maxnode=26;
using namespace std;
struct node
{int sum;node *next[maxnode];node *fail;node(){memset(next,0,sizeof(next));sum=0;fail=NULL;}
};
node *root;
void Insert(string s)
{node *p=root;for(int i=0;i<s.size();i++){int id=s[i]-'a';if(p->next[id]==NULL) p->next[id]=new node();p=p->next[id]; }p->sum++;
}
void Build()
{node *p=root;queue<node *>que;for(int i=0;i<maxnode;i++) {if(p->next[i]){p->next[i]->fail=root;que.push(p->next[i]);}else p->next[i]=root;}while(que.size()){p=que.front();que.pop();for(int i=0;i<maxnode;i++){if(p->next[i]) {p->next[i]->fail=p->fail->next[i];que.push(p->next[i]);}else p->next[i]=p->fail->next[i];}}
}
int Query(string s)
{int ans=0;queue<pair<node*,int> >status;node *p=root;for(int i=0;i<s.size();i++){int id=s[i]-'a';if(p->next[id]){p=p->next[id];node *tmp=p;while(tmp->sum){ans+=tmp->sum;status.push(make_pair(tmp,tmp->sum));tmp->sum=0;tmp=tmp->fail;}}}while(status.size()){pair<node*,int> tmp=status.front();status.pop();tmp.first->sum=tmp.second;}return ans;
}
int main()
{ios::sync_with_stdio(false);int t,n;string s;cin>>t;while(t--){root=new node();cin>>n;for(int i=1;i<=n;i++){cin>>s;Insert(s);}Build();cin>>s;cout<<Query(s)<<endl;//Delete(root);}return 0;
}

然而这个代码虽然可以AC,但是其实是有问题的。比如对于测试数据:
1
2
abc
b
abc
原本应该输出2,但我的程序输出1。由于HDU2222数据比较弱,所以我的程序AC了。

其实是我递归统计的时候弄错了,没有统计完整。接下来才是正确的AC代码:

#include<bits/stdc++.h>
const int maxnode=26;
using namespace std;
struct node
{int sum;node *next[maxnode];node *fail;node(){memset(next,0,sizeof(next));sum=0;fail=NULL;}
};
node *root;
void Insert(string s)
{node *p=root;for(int i=0;i<s.size();i++){int id=s[i]-'a';if(p->next[id]==NULL) p->next[id]=new node();p=p->next[id]; }p->sum++;
}
void Build()
{node *p=root;queue<node *>que;root->fail=root;for(int i=0;i<maxnode;i++) {if(p->next[i]){p->next[i]->fail=root;que.push(p->next[i]);}else p->next[i]=root;}while(que.size()){p=que.front();que.pop();for(int i=0;i<maxnode;i++){if(p->next[i]) {p->next[i]->fail=p->fail->next[i];que.push(p->next[i]);}else p->next[i]=p->fail->next[i];}}
}
int Query(string s)
{int ans=0;queue<pair<node*,int> >status;node *p=root;for(int i=0;i<s.size();i++){int id=s[i]-'a';if(p->next[id]){p=p->next[id];node *tmp=p;while(tmp->sum||tmp->fail!=root){if(tmp->sum){ans+=tmp->sum;status.push(make_pair(tmp,tmp->sum));tmp->sum=0;}tmp=tmp->fail;}}}while(status.size()){pair<node*,int> tmp=status.front();status.pop();tmp.first->sum=tmp.second;}return ans;
}
int main()
{ios::sync_with_stdio(false);int t,n;string s;cin>>t;while(t--){root=new node();cin>>n;for(int i=1;i<=n;i++){cin>>s;Insert(s);}Build();cin>>s;cout<<Query(s)<<endl;//Delete(root);}return 0;
}

HDU 2222(AC自动机模板)相关推荐

  1. HDU 2222 ac自动机模板

    题意: 求n个模板串在匹配串中出现了几个. SOL: 反正就是模板啦...似乎比KMP都简单----这么说似乎有点不道德...毕竟先看的KMP而他们并没有什么不同... 貌似自己的理解和他们画的图还是 ...

  2. HDU 2222 AC自动机

    AC自动机模板题. 什么是Fai指针,指向出现了的最长后缀. 怎么统计,匹配到了模式串,但是,是仅仅一个当前的节点数吗? 不是的,还要继续往Fail指针上走,统计所有的cnt之和. 这个题目设计到,每 ...

  3. hdu 2222 ac自动机

    对于ac自动机的具体内容,请看如下博客:http://www.cppblog.com/mythit/archive/2009/04/21/80633.html 写的挺好的. 要了解ac自动机就要先知道 ...

  4. hdu 2222 AC 自动机 模版(数组实现)

    AC 自动机 模版 原文匹配查找时讲错了,其他都挺好(原文博主知错懒得改 t个样例,n个单词,一个文本串,求文本串中单词出现的次数. 若给出单词ab,ab 文本ab,匹配数为2 若给出 n个不重复的单 ...

  5. Keywords Search HDU - 2222(AC自动机模板)

    题意: 给定 n个长度不超过 50的由小写英文字母组成的单词准备查询,以及一篇文章,问:文中出现了多少个待查询的单词.多组数据. 题目: In the modern time, Search engi ...

  6. Duan2baka的AC自动机模板!

    HDU[2222] Keywords Search 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机常用于多模字符串匹配问题 代码如下 ...

  7. 数单词 (AC自动机模板题)

    数单词 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 为了能够顺利通过英语四六级考试,现在大家每天早上都会早起读英语. LYH本来以为自己在6月份的考试中可以通过六级, ...

  8. NYOJ 1085 数单词 (AC自动机模板题)

    数单词 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 为了能够顺利通过英语四六级考试,现在大家每天早上都会早起读英语. LYH本来以为自己在6月份的考试中可以通过六级, ...

  9. hdu 3065 AC自动机

    // hdu 3065 AC自动机 // // 题目大意: // // 给你n个短串,然后给你一个长串,问:各个短串在长串中,出现了多少次 // // 解题思路: // // AC自动机,插入,构建, ...

最新文章

  1. Tomcat7目录结构详解(非常详细)
  2. 【网址收藏】k8s高可用集群详细搭建步骤
  3. 11.13 ethtool:查询网卡参数
  4. AI种番茄!腾讯xWUR智慧温室大赛预赛揭晓,农科院和三星等五队挺进决赛
  5. js 日期星期 带农历
  6. 数据转换之 Number
  7. Java基础入门笔记-单根继承
  8. XenDesktop 5之痛---Database Transaction Log速增
  9. R语言中如何查看已安装的R包
  10. 代码比较工具DiffMerge的下载和使用
  11. 伺服电机算功率基本公式_伺服电机功率计算选型.ppt
  12. 【Unity 资源分享】☀️ | Unity 华丽炫酷特效资源分享!万年魂环拿到手软,让你直达封号斗罗~
  13. 微信商户平台所有产品总结
  14. 基于Spring-statemachine的有限状态机(FSM)的介绍及示例
  15. 计算机有文件无法删除,w7文件夹删不掉如何删掉_win7电脑有的文件夹删不掉怎么办...
  16. 微生活时光机:去项目中挖掘JS模块化简史
  17. latex奇偶页使用不同的页眉
  18. 让AI拥有好奇心,它就可以一直看电视了
  19. 新型超级电容/法拉电容介绍
  20. Hyperledger Fabric金融区块链项目总结 之一 概述

热门文章

  1. Visual Studio 2010开发AutoCAD 2012 .net 应用程序调试时断点不起作用
  2. PYTHON DJANGO开发工资查询系统
  3. windows xp sp3 AMD双核补丁
  4. 卸载Visual Studio 2013,Visual Studio 2015和Visual Studio vNext的所有Preview / RC / RTM版本
  5. 多看Android版本WIFI传书的实现
  6. php给图片添加文字水印
  7. P4828 Nagisa loves Tomoya
  8. 洛谷月赛2018.8 T1题解(U28036 Nagisa loves Tomoya)
  9. ubuntu如何升级python版本号
  10. ITEXT 目录生成的第二种方法