hdu 2222 Keywords Search(AC自动机)
/*
啥也不说了,直接套模板。。。
*/
1 #include<iostream>
#include<map>
#include<string>
#include<cstring>
#include<queue>
#define N 500000
using namespace std; class AC_Atomata
{
public:
int nodeN;//trie树的节点个数
int trie[N][];//trie树
int f[N];//失配函数
//map<string, int>ms;//字符串到字符串编号的映射,防止出现多个字符串的模板
int last[N];// last[j]表示节点j沿着失配指针往回走时遇到的下一个单词节点的编号
int cnt;//最多在主串中出现的单词数
int val[N];//标记该节点是否为字符串的端点,该题中val[j]表示以节点j所对应的字符所结束的相同字符串的个数
int vis[N];//标记该节点已经访问过了
queue<int>q;
void init();
void buildTrie(char *p);
void getFail();
void find(char *T);
void countWords(int k);
}; void AC_Atomata::init()
{
nodeN=;
ms.clear();
memset(vis, , sizeof(vis));
memset(trie[], , sizeof(trie[]));
//memset(cnt, 0, sizeof(cnt));
cnt=;
} void AC_Atomata::buildTrie(char *p)
{
int i, u=;
for(i=; p[i]; ++i)
{
int k=p[i]-'a';
if(!trie[u][k])
{
memset(trie[nodeN+], , sizeof(trie[nodeN+])) ;
trie[u][k]=++nodeN;
val[nodeN]=;
}
u=trie[u][k];
}
++val[u];
//ms[string(p)]=v;
} void AC_Atomata::getFail()
{
int u, v, r, c;
while(!q.empty()) q.pop();
f[]=;
for(c=; c<; ++c)
{
u=trie[][c];
if(u)
{
f[u]=;
q.push(u);
last[u]=;
}
}
while(!q.empty())
{
r=q.front();
q.pop();
for(c=; c<; ++c)
{
u=trie[r][c];
if(!u) continue;
q.push(u);
v=f[r];
while(v && !trie[v][c]) v=f[v];
f[u]=trie[v][c];
last[u]=val[f[u]] ? f[u] : last[f[u]];
}
}
} void AC_Atomata::countWords(int k)
{
if(k && !vis[k])
{
//++cnt[val[k]];//k就是该单词所对应的最后一个字符的节点编号,val[k]是这个单词再输入时候的编号
vis[k]=;//表示以该节点结束的字符串已经访问过了,如果主串中再出现该字符串则不会再计算在内
cnt+=val[k];//
countWords(last[k]);
}
} void AC_Atomata::find(char *T)
{
int i, j;
for(i=, j=; T[i]; ++i)
{
int c=T[i]-'a';
while(j && !trie[j][c]) j=f[j];//一直找到可以匹配的字符节点
j=trie[j][c];
if(val[j])//单词的最后一个字符
countWords(j);
else if(last[j])//如果不是某个单词的最后一个节点
countWords(last[j]);
}
} AC_Atomata ac; char T[];
char s[]; int main()
{
int t, n, i;
scanf("%d", &t);
while(t--)
{
ac.init();
scanf("%d", &n);
for(i=; i<=n; ++i)
{
scanf("%s", s);
ac.buildTrie(s);
}
scanf("%s", T);
ac.getFail();
ac.find(T);
printf("%d\n", ac.cnt);
}
return ;
}
/*
咱再换一种方式来写,赶脚这种方式更靠谱一些!
*/
1 #include<queue>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#define N 500000
using namespace std; class TRIE
{
public:
int ch[];//建立trie树的孩子节点个数
int val;//标记该节点是否是单词的结束节点
int fail;//该节点失配时要移向的节点的编号
int last;//后缀连接,示节该点沿着失配指针往回走时遇到的下一个单词节点的编号
int vis;//标记以该点字符所结束的字符串是否已经访问过了
}; class AC_Atomata
{
public:
TRIE trie[N];//建立节点
int nodeN;//trie树的节点的个数
int cnt;//记录节点单词在主串出现的次数
AC_Atomata()
{
nodeN=;
cnt=;
trie[].val=trie[].vis=;
memset(trie[].ch, , sizeof(trie[].ch));
while(!q.empty()) q.pop();
}
queue<int>q;
void buildTrie(char *p);
void getFail();
void find(char *T);
void countWords(int k);
}; void AC_Atomata::buildTrie(char *p)
{
int i, u;
for(i=, u=; p[i]; ++i)
{
int k=p[i]-'a';
if(!trie[u].ch[k])
{
trie[u].ch[k]=++nodeN;
memset(trie[nodeN].ch, , sizeof(trie[nodeN].ch));
trie[nodeN].val=trie[nodeN].vis=;
}
u=trie[u].ch[k];
}
++trie[u].val;
} void AC_Atomata::getFail()
{
int r, u, v, c;
trie[].fail=;
for(c=; c<; ++c)
{
u=trie[].ch[c];
if(u)
{
q.push(u);
trie[u].fail=;
trie[u].last=;
}
}
while(!q.empty())
{
r=q.front();
q.pop();
for(c=; c<; ++c)
{
u=trie[r].ch[c];
if(!u) continue;
q.push(u);
v=trie[r].fail;
while(v && !trie[v].ch[c]) v=trie[v].fail;
v=trie[v].ch[c];//v 节点就是在沿着失配指针往回走时遇到的下一个单词某个字符节点的编号
trie[u].fail=v;
trie[u].last=trie[v].val ? v : trie[v].last;//last记录的总是一个完整的单词最后一个字符节点的编号
}
}
} void AC_Atomata:: find(char *T)
{
int i, j;
for(i=, j=; T[i]; ++i)
{
int k=T[i]-'a';
while(j && !trie[j].ch[k]) j=trie[j].fail;
j=trie[j].ch[k];
if(trie[j].val)
countWords(j);
else if(trie[j].last)
countWords(trie[j].last);
}
} void AC_Atomata::countWords(int n)
{
if(n && !trie[n].vis)
{
trie[n].vis=;
cnt+=trie[n].val;
countWords(trie[n].last);
}
} AC_Atomata ac;
char T[];
char s[]; int main()
{
int t, n;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i=; i<=n; ++i)
{
scanf("%s", s);
ac.buildTrie(s);
}
scanf("%s", T);
ac.getFail();
ac.find(T);
printf("%d\n", ac.cnt);
}
return ;
}
hdu 2222 Keywords Search(AC自动机)的更多相关文章
- hdu 2222 Keywords Search——AC自动机
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2222 第一道AC自动机! T了无数边后终于知道原来它是把若干询问串建一个自动机,把模式串放在上面跑:而且只 ...
- hdu 2222 Keywords Search ac自动机入门
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:有N(N <= 10000)个长度不超过50的模式串和一个长度不超过1e6的文本串. ...
- HDU 2222 Keywords Search(AC自动机模板题)
学习AC自动机请戳这里:大神blog........ 自动机的模板: #include <iostream> #include <algorithm> #include < ...
- HDU 2222 Keywords Search (AC自动机)
题意:就是求目标串中出现了几个模式串. 思路:用int型的end数组记录出现,AC自动机即可. #include<iostream> #include<cstdio> #inc ...
- hdu 2222 Keywords Search ac自动机模板
题目链接 先整理一发ac自动机模板.. #include <iostream> #include <vector> #include <cstdio> #inclu ...
- HDU 2222 Keywords Search (AC自动机)(模板题)
<题目链接> 题目大意: 给你一些单词,和一个字符串,问你这个字符串中含有多少个上面的单词. 解题分析: 这是多模匹配问题,如果用KMP的话,对每一个单词,都跑一遍KMP,那么当单词数量非 ...
- hdu 2222 Keywords Search - Aho-Corasick自动机
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submissio ...
- hdoj 2222 Keywords Search(AC自动机)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路分析:该问题为多模式匹配问题,使用AC自动机解决:需要注意的问题是如何统计该待查询的字符串包 ...
- hdu 2222 Keywords Search ac自己主动机
点击打开链接题目链接 Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Ja ...
- HDU 2222 Keywords Search AC自己主动机入门题
单词统计的题目,给出一些单词,统计有多少单词在一个文本中出现,最经典的入门题了. AC自己主动机的基础: 1 Trie. 以这个数据结构为基础的,只是添加一个fail指针和构造fail的函数 2 KM ...
随机推荐
- 原生JS 年月日、省市区 三级联动
这个算生日日期,因为是从100年前的到现年. <select id="sel_year"></select> <select id="sel ...
- 关于CSS3的小知识点之2D变换
transition过渡 transition-duration:; 运动时间 transition-delay:; 延迟时间 transition-timing-function:; 运动形 ...
- linux 查找 并删除 文件
find / -name "*.mp3" |xargs rm -rf会删除所有以mp3为扩展的文件.操作的时候先: find / -name "*.mp3" 会 ...
- eclipse导入项目出现叹号处理方法:
1.选中该项目名称,单击右键 2.点击Properties 3.选中Java Build Path 4. 5. 6. 7.出现红叉的解决办法 8. 9. 10. 11. 12. 按照以上步骤操作就可以 ...
- Python之路第一课Day9--随堂笔记之二(进程、线程、协程篇)
本节内容 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Queu ...
- js控制台输出console
介绍: js的console你可以在firefox的firedbug或者ie和google的f12调试模式下看到,这些主流浏览器的调试模式的控制可以输出一些信息,你的一些js代码测试可以直接在cons ...
- 解决word2013图片不能替换
有时我们下好文档时,想要替换里面的图片,右键时却发现没有替换图片这个选项 这是应为此时我们的文档处于兼容模式,我们可以把它另存为.docx格式,这是再右键便可发现,多了一个替换图片选项.
- Tomcat启动失败Unrecognized Windows Sockets error: 0: JVM_Bind
问题:Tomcat一直无法运行,或者是运行了报上面图片的哪些错误. 解决:关闭myeclipse,打开任务管理器(Ctrl+Alt+Delete)关闭javaw.exe这个进程,另外说一下,Tomca ...
- ADO.NET的弹性连接控制[ADO.NET idle connection resiliency]
ADO.NET连接SQL Server有时候联机会无故的中断 (例如闲置过久或是交易时间太长等因素),这时又要重新连接,在.NET Framework 4.5之前,这件事情要由开发人员自己依照ADO. ...
- jQuery 2.0.3 源码分析 Deferred(最细的实现剖析,带图)
Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html ******************构建Deferred对象时候的流程图* ...