hdu-2896-病毒侵袭(AC自动机,两种实现)
来源:互联网 发布:淘宝网中年女羽绒服 编辑:程序博客网 时间:2024/06/06 20:23
题目传送门
题意不解释 ,由于是可见字符所以只用开到94个即可。AC自动机裸题。
指针实现code:(只能用C++提交 G++是64位指针会超内存)
#include<iostream>#include<cstdio>#include<cstring>#include<queue>#define MAXN 94using namespace std;struct node{ int cut; node *son[MAXN] ,*fail; node(){ cut=0; fail=NULL; for(int i=0;i<MAXN;i++) son[i]=NULL; }};bool vis[510];node *root;void Insert(char *str,int x){ node *p=root; int i=0; while(str[i]!='\0'){ int id=str[i]-' '; if(p->son[id]==NULL) p->son[id]=new node; p=p->son[id]; i++; } p->cut=x;}void fail_build(){ node *p=root; queue<node *>q; q.push(p); while(!q.empty()){ p=q.front(); q.pop(); for(int i=0;i<MAXN;i++) { if(p->son[i]!=NULL) { if(p==root) p->son[i]->fail=root; else { node *temp=p->fail; while(temp!=NULL){ if(temp->son[i]!=NULL){ p->son[i]->fail=temp->son[i]; break; } temp=temp->fail; } if(temp==NULL) p->son[i]->fail=root; } q.push(p->son[i]); } } }}bool AC_find(char *str){ node *p=root; bool falg=false; int i=0; while(str[i]!='\0'){ //printf("%d\n",i); int id=str[i]-' '; while(p->son[id]==NULL&&p!=root) p=p->fail; p=p->son[id]; if(p==NULL) p=root; node *temp=p; while(temp!=NULL&&temp->cut!=0){ vis[temp->cut]=true; //temp->cut=-1; temp=temp->fail; falg=true; } i++; } return falg;}void del(node *p){ for(int i=0;i<MAXN;i++) if(p->son[i]!=NULL) del(p->son[i]); delete(p);}int main(){ char str[10010],str1[210]; int n,m; scanf("%d",&n); root=new node; for(int i=1;i<=n;i++){ scanf("%s",str1); Insert(str1,i); } fail_build(); scanf("%d",&m); int ans=0; for(int i=1;i<=m;i++){ scanf("%s",str); bool falg=0; memset(vis,0,sizeof(vis)); if(AC_find(str)){ans++;falg=1;} if(falg) printf("web %d:",i); for(int i=0;i<=n;i++){ if(vis[i]) printf(" %d",i); } if(falg) printf("\n"); } printf("total: %d\n",ans); return 0;}
数组实现code:(数组实现,一维数组代表 节点个数)数组既节省时间也节省空间 但不太好理解 如何取舍自己看吧
#include <iostream>#include <stdio.h>#include <string.h>#include <queue>#include <algorithm>using namespace std;const int allSon = 130; ///包含所有的字符const int maxn = 100005;int node[maxn][allSon]; ///字典树节点int fail[maxn]; ///fail指针int num[maxn]; ///num[i]代表以第i个节点为结尾的单词个数int vis[maxn]; ///标记int index[maxn]; ///用来存放模式串的编号char patten[maxn]; ///模式串char text[maxn]; ///文本串int ans[maxn];int id; ///用来给节点编号int total; ///统计总共有多少个网站感染病毒///将模式串插入到字典树,传入的模式串的编号void insertPatten(int identifier){ int p = 0; ///指向根节点 int pos = 0; ///下标 int len = strlen(patten); while(pos < len) { int ch = patten[pos]; if(node[p][ch]==-1) ///节点不存在 { memset(node[id],-1,sizeof(node[id])); ///孩子节点都置空 num[id] = 0; fail[id] = -1; vis[id] = -1; node[p][ch] = id++; } p = node[p][ch]; pos++; } num[p]++; index[p] = identifier; ///存储编号}///找fail指针,构造AC自动机void build_AC_automaton(){ queue<int>qu; int p = 0; ///最开始指向根节点 qu.push(p); while(!qu.empty()) { p = qu.front(); qu.pop(); for(int i = 0; i < allSon; i++) { if(node[p][i]!=-1) ///第i个孩子存在 { if(p == 0) ///如果p是根,根的孩子fail指向根 { fail[node[p][i]] = 0; } else { int temp = fail[p]; while(temp != -1) { if(node[temp][i] != -1) { fail[node[p][i]] = node[temp][i]; break; } temp = fail[temp]; } if(temp == -1) { fail[node[p][i]] = 0; } } qu.push(node[p][i]); } } }}///在AC自动机中进行查询,传入参数是第i个网站的编号。void find_in_AC_automaton(int identify){ int p = 0; int pos = 0; int t = 0; while(text[pos]!='\0') { int ch = text[pos]; while(node[p][ch]==-1 && p!=0) p = fail[p]; p = node[p][ch]; if(p == -1) p = 0; int temp = p; /**由于别的字符串还要过来匹配,所以节点的num 值不能进行改变,我们可以用vis数组来实现标记,避免 重复统计**/ while(temp!=0 && vis[temp]!=identify) { vis[temp] = identify; if(num[temp]) ///代表网站有一个病毒 { ans[t++] = index[temp]; } temp = fail[temp]; } ///由于一个网站病毒最多三个,所以找够三个就出来,不要浪费时间做无用功。 if(t >= 3) break; pos++; } if(t != 0) { total++; printf("web %d:",identify); sort(ans,ans+t); for(int i = 0; i < t; i++) printf(" %d",ans[i]); printf("\n"); }}void init(){ memset(node[0],-1,sizeof(node[0])); num[0] = 0; fail[0] = -1; index[0] = -1; vis[0] = -1; id = 1; total = 0;}int main(){ int N,M; while(~scanf("%d",&N)) { init(); ///初始化根节点 for(int i = 1; i <= N; i++) { scanf("%s",patten); insertPatten(i); } build_AC_automaton(); scanf("%d",&M); for(int i = 1; i <= M; i++) { scanf("%s",text); find_in_AC_automaton(i); } printf("total: %d\n",total); } return 0;}
阅读全文
1 0
- hdu-2896-病毒侵袭(AC自动机,两种实现)
- HDU 2896 病毒侵袭(AC自动机)
- HDU 2896 病毒侵袭 (AC自动机)
- hdu 2896 病毒侵袭(AC自动机)
- hdu 2896 病毒侵袭(AC自动机)
- hdu 2896 病毒侵袭(AC自动机)
- HDU 2896 病毒侵袭(AC自动机)
- HDU 2896 病毒侵袭 (AC自动机)
- HDU 2896 - 病毒侵袭 (AC自动机)
- hdu 2896 病毒侵袭(AC自动机)
- HDU 2896 病毒侵袭(AC自动机)
- HDU 2896 病毒侵袭(AC自动机)
- HDU 2896 病毒侵袭 (AC自动机)
- HDU 2896 病毒侵袭 (AC自动机)
- HDU 2896 病毒侵袭(AC自动机)
- HDU 2896 病毒侵袭(AC自动机)
- HDU 2896 病毒侵袭(AC自动机)
- HDU 2896 病毒侵袭(ac自动机)
- 自顶向下,逐步求精
- jdk8新特性(附jdk5/jdk6/jdk7新特性)
- JavaDVD管理系统
- 程序员如何入门 Python 爬虫
- 《剑指offer》刷题笔记(时间空间效率的平衡):第一个只出现一次的字符
- hdu-2896-病毒侵袭(AC自动机,两种实现)
- C语言操作符
- numpy: np.ndarray.flatten
- 1.1:文件过滤
- xshell连接centos经常掉线的问题
- 通过placeholder实现前向传播算法
- Eclipse配置 之 修改JSP默认编码
- 面试之JavaWeb篇(十三)
- 解决:Navicat远程连接mysql失败