/*
啥也不说了,直接套模板。。。
*/
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自动机)的更多相关文章

  1. hdu 2222 Keywords Search——AC自动机

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2222 第一道AC自动机! T了无数边后终于知道原来它是把若干询问串建一个自动机,把模式串放在上面跑:而且只 ...

  2. hdu 2222 Keywords Search ac自动机入门

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:有N(N <= 10000)个长度不超过50的模式串和一个长度不超过1e6的文本串. ...

  3. HDU 2222 Keywords Search(AC自动机模板题)

    学习AC自动机请戳这里:大神blog........ 自动机的模板: #include <iostream> #include <algorithm> #include < ...

  4. HDU 2222 Keywords Search (AC自动机)

    题意:就是求目标串中出现了几个模式串. 思路:用int型的end数组记录出现,AC自动机即可. #include<iostream> #include<cstdio> #inc ...

  5. hdu 2222 Keywords Search ac自动机模板

    题目链接 先整理一发ac自动机模板.. #include <iostream> #include <vector> #include <cstdio> #inclu ...

  6. HDU 2222 Keywords Search (AC自动机)(模板题)

    <题目链接> 题目大意: 给你一些单词,和一个字符串,问你这个字符串中含有多少个上面的单词. 解题分析: 这是多模匹配问题,如果用KMP的话,对每一个单词,都跑一遍KMP,那么当单词数量非 ...

  7. hdu 2222 Keywords Search - Aho-Corasick自动机

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submissio ...

  8. hdoj 2222 Keywords Search(AC自动机)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路分析:该问题为多模式匹配问题,使用AC自动机解决:需要注意的问题是如何统计该待查询的字符串包 ...

  9. hdu 2222 Keywords Search ac自己主动机

    点击打开链接题目链接 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Ja ...

  10. HDU 2222 Keywords Search AC自己主动机入门题

    单词统计的题目,给出一些单词,统计有多少单词在一个文本中出现,最经典的入门题了. AC自己主动机的基础: 1 Trie. 以这个数据结构为基础的,只是添加一个fail指针和构造fail的函数 2 KM ...

随机推荐

  1. 浅谈我对 jQuery 的了解

    总述 0 获取 jQuery 对象 1 对象跳转 2 方法调用 3 常用API 4 $(…); 5 jQuery 对象获取 6 Data 相关方法 7 选择器 8 基本的过滤器 9 内容过滤选择器 1 ...

  2. CI框架使用PHPmail插件发送QQ邮件:

    有助请顶,不好请评.0:33 2016/3/12CI框架使用PHPmail插件发送QQ邮件:发送成功,不过修改了主机参数,还包含了一个phpmail中的一个另外的文件,详见下方:参见:http://c ...

  3. 【DFS】POJ 1321

    POJ 1321 棋盘问题 题意:中文题不解释. 思路:经典DP,比较取巧的想法是一行行(按照题目意思一行最多只能放一个)来看,标记一列列.注意考虑到有些行可能不放的情况. /** Sample In ...

  4. 抓包工具Wireshark过滤器

    抓包工具WireShark分为两种过滤器: 捕捉过滤器(CaptureFilters) 显示过滤器(DisplayFilters) 捕捉过虑器语法: Protocol  Direction  Host ...

  5. 简单的jquery选项卡效果

    html部分 <ul class="tab"> <li>最新</li> <li class="cur">热门&l ...

  6. Jenkins中构建Testcomplete项目的方法介绍

    Jenkins的部署在上一篇随笔中已经和大家介绍了,下面我们介绍一下再Jenkins中构建testcomplete项目.我这里使用的是Testcomplete11,下面详细介绍一下构建步骤. 1.Je ...

  7. 深入super,看Python如何解决钻石继承难题 【转】

    原文地址 http://www.cnblogs.com/testview/p/4651198.html 1.   Python的继承以及调用父类成员 python子类调用父类成员有2种方法,分别是普通 ...

  8. linux ping加执行时间

    [root@back_zabbix_100 ~]# ping 10.10.30.250 | awk '{print $0"\t" strftime("%H:%M:%S&q ...

  9. MySQL选择合适的数据类型

    一.char和varchar char是固定长度的,查询速度比varchar速度快的多.char的缺点是浪费存储空间. 检索char列时,返回的结果会删除尾部空格,所以程序需要对为空格进行处理. 对于 ...

  10. bzoj 2739 最远点

    Description 给你一个N个点的凸多边形,求离每一个点最远的点. Input 本题有多组数据,第一行一个数T,表示数据组数. 每组数据第一行一个数N,表示凸多边形点的个数,接下来N对数,依次表 ...