/*
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. case when then else end 用法

    前段时间做项目过程中制作报表时编写的sql需要用到的case when then else end,因此将case的用法总结一下吧. CASE命令有两种语句格式:语法形式1:CASE expressi ...

  2. bzoj 3718

    题意:戳这里 思路:很容易发现对于一个车能否移动到最终的位置只要判断路径中得最大高度与自身高端之和是否>w即可. 那么就可以转化为逆序对得最大数问题..即对于每一辆车,判断有那些最初在他前面,而 ...

  3. hdu 4193 - Non-negative Partial Sums(滚动数列)

    题意: 给定一个由n个整数组成的整数序列,可以滚动,滚动的意思就是前面k个数放到序列末尾去.问有几种滚动方法使得前面任意个数的和>=0. 思路: 先根据原来的数列求sum数组,找到最低点,然后再 ...

  4. linux下显示dd命令的进度:

    linux下显示dd命令的进度: dd if=/dev/zero of=/tmp/zero.img bs=10M count=100000 想要查看上面的dd命令的执行进度,可以使用下面几种方法: 比 ...

  5. libmegjb.so加载问题调试和分析

    欢迎转载opendevkit文章, 文章原始地址: http://www.opendevkit.com/?e=70 01-01 00:09:21.084: D/dalvikvm(10394): Try ...

  6. 七牛php sdk 生成上传凭证时出现 undefined function Qiniu_SetKeys()

    将qiniu/http.php文件改名即可,原因是xampp等集成环境会安装pear存在了http.php

  7. [Xamarin] 從Xamarin中呼叫 *.jar 的 library - 呼叫篇 (转帖)

    上篇文章我們建立一個很簡單的Library : com.example.blackfactory.UtilFunc 現在我們要在Xamarin 中呼叫囉! 首先我們要先成立一個橋接的專案 JARBri ...

  8. karma作为jQuery单元测试Runner

    karma作为angular测试runner出现,如果你使用过karma一定感受到这很不错的javascript测试runner.简单干净的配置文件karma.config.js,以及karma in ...

  9. Aspectj 实现Method条件运行

    最近我花了半个小时实现了一个Method的按自定义条件运行的plugin,Condition-Run.实现场景是由于我所工作的客户经常会是在同一个代码集上实现多个Brand,所以有些功能只会限制是几个 ...

  10. 页面动态加入<script>标签并执行代码

    在页面中动态追加html片段的时候,有时候动态添加的代码会含有<script>标签,比如用了一些模板引擎,或者你的代码有些复杂的时候.然而我们用DOM提供的innerHTML方式来添加代码 ...