/*
hdu 2896 病毒侵袭 ac自动机
从题意得知,模式串中没有重复的串出现,所以结构体中可以将last[](后缀链接)数组去掉
last[]数组主要是记录具有相同后缀模式串的末尾节点编号 。本题中主要是计算每一个模式串
在主串中有没有出现过,而不是计算出现过多少次,所以将last[]数组省掉....
*/
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 210*500
using namespace std;
class AC_atomata
{
public:
int trie[N][], f[N], val[N];
int vis[];
int nodeN;
int total;
queue<int>q;
void init()
{
nodeN=;
val[]=;
total=;
while(!q.empty()) q.pop();
memset(trie[], , sizeof(trie[]));
}
void build(char *str, int index);//建立trie树
void getFail();//失配函数
void find(char *T, int n, int index);//查找函数
}; void AC_atomata::build(char *str, int index)
{
int i, u;
for(i=, u=; str[i]; ++i)
{
int ch=str[i];
if(!trie[u][ch])
{
trie[u][ch]=++nodeN;
memset(trie[nodeN], , sizeof(trie[nodeN]));
}
u=trie[u][ch];
val[u]=;
}
val[u]=index;
} void AC_atomata::getFail()
{
int r, u, v, i;
f[]=;
for(i=; i<; ++i)
{
if(trie[][i])
{
q.push(trie[][i]);
f[trie[][i]]=;
}
}
while(!q.empty())
{
r=q.front();
q.pop();
for(i=; i<; ++i)
{
u=trie[r][i];
if(!u) continue;
q.push(u);
v=f[r];
while(v && !trie[v][i]) v=trie[v][i];
f[u]=trie[v][i];
}
}
} void AC_atomata::find(char *T, int n, int index)
{
int i, u;
int cnt=, v[];
memset(v, , sizeof(v));
memset(vis, , sizeof(vis));//每一次查找将数组初始化,开始忘记初始化了, 哇了好多次
for(i=, u=; T[i]; ++i)
{
int ch=T[i];
while(u && !trie[u][ch]) u=f[u];
u=trie[u][ch];
if(val[u] && !vis[val[u]])
{
v[cnt++]=val[u];
vis[val[u]]=;
if(cnt>) break;
}
}
if(cnt>)
{
++total;
printf("web %d:", index);
sort(v, v+);
for(i=; i<; ++i)
if(v[i]) printf(" %d", v[i]);
printf("\n");
}
} AC_atomata ac;
char T[], s[]; int main()
{
int n, m, i;
while(scanf("%d", &n)!=EOF)
{
ac.init();
for(i=; i<=n; ++i)
{
scanf("%s", s);
ac.build(s, i);
}
ac.getFail();
scanf("%d", &m);
for(i=; i<=m; ++i)
{
scanf("%s", T);
ac.find(T, n, i);
}
printf("total: %d\n", ac.total);
}
return ;
}
 /*
上面的程序过了,感觉数据很水....
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 100005
#define M 505
using namespace std;
int n, m;
class AC_atomata
{
public:
int trie[N][128], fail[N];
int cnt;
int vis[M];//标记边
int nodeN;//节点数
int val[N];//标记字符节点是否为单词末尾
queue<int>q;
void init();
void build(char *T, int index) ;
void getFail();
void find(char *S, int index);
}; void AC_atomata:: init()
{
while(!q.empty()) q.pop();
memset(trie[0], 0, sizeof(trie[0]));
nodeN=0;
cnt=0;
memset(val, 0, sizeof(val));
} void AC_atomata:: build(char *T, int index)
{
int i, u=0;
for(i=0; T[i]; ++i)
{
if(trie[u][T[i]]==0)
{
trie[u][T[i]]=++nodeN;
memset(trie[nodeN], 0, sizeof(trie[nodeN]));
}
val[u]=0;
u=trie[u][T[i]];
}
val[u]=index;
} void AC_atomata:: getFail()
{
int r, u, v;
int c, root=0;
fail[root]=0;
for(c=0; c<128; ++c)
{
if(v=trie[root][c])
{
fail[v]=root;
q.push(v);
}
}
while(!q.empty())
{
r=q.front(); q.pop();
for(c=0; c<128; ++c)
{
u=trie[r][c];
if(!u)//该节点不存在,也就是查找过程中每一个节点都是平等的
trie[r][c]=trie[fail[r]][c];
else
{
fail[u]=trie[fail[r]][c];
q.push(u);
}
}
}
} void AC_atomata:: find(char *S, int index)
{
int cur, root, count=0;
cur=root=0;
memset(vis, 0, sizeof(vis));
for(int i=0; S[i]; ++i)
{
cur=trie[cur][S[i]];
int next=cur;

//这个while循环就是last[]数组实现的功能,只不过是last[]数组记录的总是单词结尾字符的节点的编号
          //而我们通过沿着 next 节点的失配方向一直搜索, 也可以寻找到 以next节点所对应字符结尾的单词

        while(next!=root)
{
if(val[next])
{
vis[val[next]]=1;
count++;
}
next=fail[next];
}
}
if(count>0)
{
++cnt;
printf("web %d:", index);
for(int i=1; i<=n; ++i)
if(vis[i])
printf(" %d", i);
printf("\n");
}
} char t[205], s[10005];
AC_atomata ac;
int main()
{
int i;
while(scanf("%d", &n)!=EOF)
{
ac.init();
for(i=1; i<=n; ++i)
{
scanf("%s", t);
ac.build(t, i);
}
ac.getFail();
scanf("%d", &m) ;
for(i=1; i<=m; ++i)
{
scanf("%s", s);
ac.find(s, i);
}
printf("total: %d\n", ac.cnt);
}
return 0;
}

hdu 2896 病毒侵袭 ac自动机的更多相关文章

  1. hdu 2896 病毒侵袭 AC自动机(查找包含哪些子串)

    病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  2. hdu 2896 病毒侵袭 AC自动机 基础题

    病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  3. HDU 2896 病毒侵袭 (AC自己主动机)

    pid=2896">http://acm.hdu.edu.cn/showproblem.php?pid=2896 病毒侵袭 Time Limit: 2000/1000 MS (Java ...

  4. hdu 2896 病毒侵袭_ac自动机

    题意:略 思路:套用ac自动机模板 #include <iostream> #include<cstdio> #include<cstring> using nam ...

  5. HDU 2896 病毒侵袭 AC自己主动机题解

    本题是在text里面查找key word的增强版.由于这里有多个text. 那么就不能够简单把Trie的叶子标志记录改动成-1进行加速了,能够使用其它技术.我直接使用个vis数组记录已经訪问过的节点, ...

  6. HDU 2896 病毒侵袭(AC自动机水)

    病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  7. HDU 2896 病毒侵袭(AC自动机)

    病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  8. HDU 2896 病毒侵袭【AC自动机】

    <题目链接> Problem Description 当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻....在这样的时刻,人们却异常兴奋——我们能在有生之年看到500年一 ...

  9. hdu2896 病毒侵袭 ac自动机

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=2896 题目: 病毒侵袭 Time Limit: 2000/1000 MS (Java/Othe ...

随机推荐

  1. ButterKnife的原理简述

    ButterKnife的原理简述 注解处理器Java5 中叫APT(Annotation Processing Tool),在Java6开始,规范化为 Pluggable Annotation Pro ...

  2. week 2 日志

    周二 css知多少(3)——样式来源与层叠规则 http://www.cnblogs.com/wangfupeng1988/p/4277959.htmlcss知多少(4)——解读浏览器默认样式 htt ...

  3. PDF2

    itex生成PDF文档示例 package dao.other; import java.awt.Color; import java.io.File; import java.io.FileInpu ...

  4. 软件工程课设day3

    下载昨日新版本程序,完成修复项目的测试. 与组内成员讨论,确认项目新模块功能“吐槽墙”的设计方向与实现形式——因为项目为便捷工具类,社区形式的实现方式与项目本质背道而驰.因此决定以“点击目标课程条目, ...

  5. C#面向对象编程进阶(一) ——实现栈

    如何用C#编写一个栈类? 关键在于这样的一个类应该如何设计呢?首先要确立面向对象的编程思想,即类是对实体进行合理地抽象和建模,而这种思想将贯彻在我们编程的整个过程中.下面我们一步一步来做. 1.类方法 ...

  6. AJAX原理总结

    AJAX全称 Asynchronous JavaScript and XML(异步的JavaScript 和XML) 同步和异步 异步传输是面向字符的传输,单位是字符 同步传输是面向比特,单位是帧,传 ...

  7. 阿里巴巴-OS事业群-OS手机事业部-系统服务部门招聘Java开发工程师,有意者请进来

    我是阿里巴巴-OS事业群-OS手机事业部-系统服务部的开发工程师,正在招聘Java开发工程师. 以下是职位描述: 岗位名称:Java开发工程师 招聘人数:5人 生效日期:2014-03-12 结束日期 ...

  8. 【转】 Nginx深入详解之多进程网络模型

    [转自]http://blog.chinaunix.net/uid-22312037-id-3974068.html 一.进程模型        Nginx之所以为广大码农喜爱,除了其高性能外,还有其 ...

  9. listview(3、动态刷新)

    listview的动态刷新主要是调用adapter的notifyDataSetChanged. 在下面的例子中除了记录正常的刷新外,还记录一种错误的情况(注释掉的),作为备忘. notifyDataS ...

  10. 关于Windows窗口框架

    我们知道Windows的窗口消息处理函数是C方式, 面向过程的, 所以窗口框架的基本任务就是将它转成面向对象的方式, 确切的说如何将消息处理函数第一参数HWND转成对象指针. 关于这个问题, 其实网上 ...