HDU 2222(AC自动机模板)
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自动机模板)相关推荐
- HDU 2222 ac自动机模板
题意: 求n个模板串在匹配串中出现了几个. SOL: 反正就是模板啦...似乎比KMP都简单----这么说似乎有点不道德...毕竟先看的KMP而他们并没有什么不同... 貌似自己的理解和他们画的图还是 ...
- HDU 2222 AC自动机
AC自动机模板题. 什么是Fai指针,指向出现了的最长后缀. 怎么统计,匹配到了模式串,但是,是仅仅一个当前的节点数吗? 不是的,还要继续往Fail指针上走,统计所有的cnt之和. 这个题目设计到,每 ...
- hdu 2222 ac自动机
对于ac自动机的具体内容,请看如下博客:http://www.cppblog.com/mythit/archive/2009/04/21/80633.html 写的挺好的. 要了解ac自动机就要先知道 ...
- hdu 2222 AC 自动机 模版(数组实现)
AC 自动机 模版 原文匹配查找时讲错了,其他都挺好(原文博主知错懒得改 t个样例,n个单词,一个文本串,求文本串中单词出现的次数. 若给出单词ab,ab 文本ab,匹配数为2 若给出 n个不重复的单 ...
- Keywords Search HDU - 2222(AC自动机模板)
题意: 给定 n个长度不超过 50的由小写英文字母组成的单词准备查询,以及一篇文章,问:文中出现了多少个待查询的单词.多组数据. 题目: In the modern time, Search engi ...
- Duan2baka的AC自动机模板!
HDU[2222] Keywords Search 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机常用于多模字符串匹配问题 代码如下 ...
- 数单词 (AC自动机模板题)
数单词 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 为了能够顺利通过英语四六级考试,现在大家每天早上都会早起读英语. LYH本来以为自己在6月份的考试中可以通过六级, ...
- NYOJ 1085 数单词 (AC自动机模板题)
数单词 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 为了能够顺利通过英语四六级考试,现在大家每天早上都会早起读英语. LYH本来以为自己在6月份的考试中可以通过六级, ...
- hdu 3065 AC自动机
// hdu 3065 AC自动机 // // 题目大意: // // 给你n个短串,然后给你一个长串,问:各个短串在长串中,出现了多少次 // // 解题思路: // // AC自动机,插入,构建, ...
最新文章
- Tomcat7目录结构详解(非常详细)
- 【网址收藏】k8s高可用集群详细搭建步骤
- 11.13 ethtool:查询网卡参数
- AI种番茄!腾讯xWUR智慧温室大赛预赛揭晓,农科院和三星等五队挺进决赛
- js 日期星期 带农历
- 数据转换之 Number
- Java基础入门笔记-单根继承
- XenDesktop 5之痛---Database Transaction Log速增
- R语言中如何查看已安装的R包
- 代码比较工具DiffMerge的下载和使用
- 伺服电机算功率基本公式_伺服电机功率计算选型.ppt
- 【Unity 资源分享】☀️ | Unity 华丽炫酷特效资源分享!万年魂环拿到手软,让你直达封号斗罗~
- 微信商户平台所有产品总结
- 基于Spring-statemachine的有限状态机(FSM)的介绍及示例
- 计算机有文件无法删除,w7文件夹删不掉如何删掉_win7电脑有的文件夹删不掉怎么办...
- 微生活时光机:去项目中挖掘JS模块化简史
- latex奇偶页使用不同的页眉
- 让AI拥有好奇心,它就可以一直看电视了
- 新型超级电容/法拉电容介绍
- Hyperledger Fabric金融区块链项目总结 之一 概述
热门文章
- Visual Studio 2010开发AutoCAD 2012 .net 应用程序调试时断点不起作用
- PYTHON DJANGO开发工资查询系统
- windows xp sp3 AMD双核补丁
- 卸载Visual Studio 2013,Visual Studio 2015和Visual Studio vNext的所有Preview / RC / RTM版本
- 多看Android版本WIFI传书的实现
- php给图片添加文字水印
- P4828 Nagisa loves Tomoya
- 洛谷月赛2018.8 T1题解(U28036 Nagisa loves Tomoya)
- ubuntu如何升级python版本号
- ITEXT 目录生成的第二种方法