/*
啥也不说了,直接套模板。。。
*/
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. oracle 导出指定的存储过程

    只能导出以下类型: PROCEDURE PACKAGE PACKAGE BODY TYPE BODY FUNCTION TYPE 也就是,表需要单独导出并导入(已经能俭省很多手动操作了). SET e ...

  2. Cocopod

    装了好几天,这个是比较全面的,大家可以看看帮助一下 1.新建一个项目,名称:CPTest 2.打开终端,输入"cd"+空格,然后将文件夹拖入到后面 3.回车后继续输入vim Pod ...

  3. java记录

    1. 包装类与自动装箱问题:在justjavac的博客上看到翻译的一篇文章 离开java,寻找更佳语言的十大理由 中关于自动装箱的一个描述: 这个特性是为了解决因原生类型的存在所导致的问题,在Java ...

  4. Jenkins 集成打包和上传 App Store 的冲突

    周一下午用 Jenkins 集成打包,遇到了一个很奇怪的问题,之前上传到 APP Store 的时候 Build Settings->“Code Signing Resource Rules P ...

  5. [转]Android ListView 与 RecyclerView 对比浅析—缓存机制

    从源码角度剖析ListView 与 RecyclerView 缓存机制的不同 https://zhuanlan.zhihu.com/p/23339185 原文地址:http://dev.qq.com/ ...

  6. SQL Server

    1.通过触发器来级联删除: 具体的触发器代码如下: Create TRIGGER [dbo].[DeleteRelatedProducts] ON [dbo].[ProductCategory]  A ...

  7. USACO翻译:USACO 2014 DEC Silver三题

    USACO 2014 DEC SILVER 一.题目概览 中文题目名称 回程 马拉松 奶牛慢跑 英文题目名称 piggyback marathon cowjog 可执行文件名 piggyback ma ...

  8. doduicms 手机和pc同步 链接处理

    sitem.aspx 加上 Session.Add("ismobile", "1"); string mobile = HttpContext.Current. ...

  9. ArcGIS10的附件功能

    转自 积思园 http://blog.csdn.net/linghe301/article/details/6386176 老是忘记怎么使用这个ArcGIS10的附件功能,这次就做个记录吧. 在项目应 ...

  10. AJXA!让体验更美好

    AJXA = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 不是新的编程语言,而是一种使用现有标准的新方法. AJAX 是与服 ...