/*
啥也不说了,直接套模板。。。
*/
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. 闭包和重写函数 返回IE浏览器版本号

    开发过程中我们有时候需要知道IE的版本号,我们知道得到IE的版本号的方法: var v = 3, div = document.createElement('div'), all = div.getE ...

  2. 微信——获取用户基本信息及openid 、access_token、code

    获取用户信息,需要获取 access_token.openid 然后调用接口https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCES ...

  3. MAC帧和IP包的分析

    ping了12次岭南师范学院官网后退出   抓到的包如下   各个名词解释

  4. jquery 获取奇数索引的元素

    $(".btn-xs:odd").click(function(){ var $buy_num=$(this).prev("#buy_num").val(); ...

  5. jmobile学习之路 ---- 视口

    当我们的浏览器在窗口最大化的时候,此时屏幕的宽度,就是我们桌面的分辨率.这个规则仅仅适用于PC! 我们试图在iPhone中输出屏幕宽度,你会发现屏幕宽度是980!居然和PC屏幕差不多大! 苹果主导的这 ...

  6. bootstrap之强调文本的类(带颜色)

    bootstrap之强调文本的类(带颜色) <small>本行内容是在标签内</small><br> <strong>本行内容是在标签内</str ...

  7. arcmap插件不能调试(转)

    1, 进入ArcGIS Desktop安装目录,如:C:\Program Files\ArcGIS\Desktop10.0 2, 进入Bin文件夹,备份ArcMap.exe.config文件,以备恢复 ...

  8. angularjs 解决ng-repeat数组内重复对象报错的问题

    ng-repeat 循环数组内元素时,如果数组内元素重复,angular会抛出异常: Error: [ngRepeat:dupes] http://errors.angularjs.org/1.4.3 ...

  9. 基于webdriver的jmeter性能测试-Eclipse+Selenium+JUnit生成jar包

    续接 打开eclipse新建java项目,如下图所示: 输入项目名称后点击"完成"按钮,如下图所示: eclipse中新建一个java项目,如下图所示: 添加类库,如下图所示: 在 ...

  10. Tree菜单 复选框选中控制DEMO

    java 对应实体类属定义 public class AccoSysmanResource{        /**     * 资源类型     */    private Integer resou ...