HDU 2222 (AC自动机)
来源:互联网 发布:淘宝客推广宣传海报 编辑:程序博客网 时间:2024/05/29 09:03
http://acm.hdu.edu.cn/showproblem.php?pid=2222
AC自动机模板题
数组版本(参考kuangbin和昀神)写的精简巧妙,很喜欢.
(找失败指针中,原来node[i][j]表示字典树i节点的字符为j的儿子的编号。
现在扩展一下,如果i没有字符j这个儿子那么node[i][j]就是i节点沿着失败指针一直走到有字符为j的儿子的节点的编号,若不存在,指向根。相当于一个路径压缩的思想)
Code:
#include <cstdio>#include <cstring>#include <queue>using namespace std;const int maxn =1000010;struct Trie{ int node[maxn][26],fail[maxn],num[maxn],root,L; int newnode() { for(int i=0;i<26;i++) node[L][i]=-1; num[L]=0; return L++; } void init(){L=0,root=newnode();} void insert_fun(char buf[]) { int now=root; int len=strlen(buf); for(int i=0;i<len;i++) { if(node[now][buf[i]-'a']==-1) node[now][buf[i]-'a']=newnode(); now=node[now][buf[i]-'a']; } num[now]++; } void build() { queue<int> q; fail[root]=root; for(int i=0;i<26;i++) if(node[root][i]==-1) node[root][i]=root; else { fail[node[root][i]]=root; q.push(node[root][i]); } while(!q.empty()) { int now=q.front(); q.pop(); for(int i=0;i<26;i++) { if(node[now][i]==-1) node[now][i]=node[fail[now]][i]; //将该边指向当前节点fail指针指向的相应字符连接的节点 else { //将儿子节点的fail指针指向当前节点fail指针指向相应字符接的节点 fail[node[now][i]]=node[fail[now]][i]; q.push(node[now][i]); } } } } int query(char buf[]) { int len=strlen(buf); int now=root,res=0; for(int i=0;i<len;i++) { now=node[now][buf[i]-'a']; int temp=now; while(temp!=root&& num[temp]!=-1) { res+=num[temp]; num[temp]=-1; temp=fail[temp]; } } return res; }};Trie ac;char buf[maxn];int main(){ int T,n; scanf("%d",&T); while(T--) { scanf("%d",&n); ac.init(); for(int i=0;i<n;i++) { scanf("%s",buf); ac.insert_fun(buf); } ac.build(); scanf("%s",buf); int ans=ac.query(buf); printf("%d\n",ans); } return 0;}
#include <cstdio>#include <iostream>#include <cstring>using namespace std;#define T_SIZE 1000000#define P_SIZE 50#define TOTAL_P 10000struct trie{ //利用结构体来封装字典树的节点 trie* next[26]; trie* fail; int num; trie() { for(int i=0;i<26;i++) next[i]=NULL; fail=NULL; num=0; }};char T[T_SIZE+1];char P[P_SIZE+1];trie *q[TOTAL_P*P_SIZE];void insert(trie* root,char* s){ trie *p=root; for(int i=0;s[i]!='\0';i++) { if(p->next[s[i]-'a']==NULL) p->next[s[i]-'a']=new trie; p=p->next[s[i]-'a']; } p->num++;}void build_ac_automation(trie* root)//利用广搜构建失败指针{ int head=0,tail=0; q[tail++]=root; while(head!=tail) { trie *front=q[head++]; //front为队头 for(int i=0;i<26;i++) if(front->next[i]!=NULL) //遍历队头元素的子节点 { trie* p=front->fail; while(p!=NULL) //只有根节点的失败指针为NULL { if(p->next[i]!=NULL) { front->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL) front->next[i]->fail=root; q[tail++]=front->next[i]; } }}int ac_find(trie* root,char* T){ trie* p =root; int sum=0; for(int i=0,len=strlen(T);i<len;i++) { while(p->next[T[i]-'a']==NULL&& p!=root) { p=p->fail; } if(p->next[T[i]-'a']!=NULL) p=p->next[T[i]-'a']; trie* temp =p; while(temp!=root && temp->num!=-1) { sum+=temp->num; temp->num=-1; temp=temp->fail; } } return sum;}int main(){ int t; for(scanf("%d",&t);t>0;t--) { trie *root =new trie; int n; scanf("%d",&n); getchar(); for(int i=0;i<n;i++) { gets(P); insert(root,P); } build_ac_automation(root); gets(T); printf("%d\n",ac_find(root,T)); } return 0;}
阅读全文
0 0
- HDU 2222 (AC自动机)
- Hdu 2222(AC 自动机)
- HDU 2222 (AC自动机)
- AC自动机 hdu 2222
- HDU 2222(AC 自动机)
- hdu 2222 AC自动机
- HDU 2222 AC自动机
- Hdu 2222 [AC自动机]
- hdu 2222 AC自动机 。。
- hdu 2222 AC自动机
- hdu 2222 ac自动机
- hdu 2222 AC自动机
- HDU 2222 AC自动机
- HDU 2222 AC自动机
- hdu 2222 ac自动机
- hdu 2222 AC自动机
- ac自动机 hdu 2222
- hdu 2222 AC自动机
- PAT (Advanced) 1003. Emergency (25)
- 集合的所有子集的算法
- 格式化输出n天后的时间(java实现 )
- 论文阅读笔记:SSD: Single Shot MultiBox Detector
- Linux下tomcat如何加端口号
- HDU 2222 (AC自动机)
- Unity3d:世界坐标系
- 实训第一次课
- 欢迎使用CSDN-markdown编辑器
- 算法作业-统计数字问题&字典序问题&最多约数问题
- JSP中的scriptlet和注释
- 数据库学习纪要(十三):SQL Sever介绍-5
- NodeMCU与贝壳物联通信实现远程控制
- JAVA学习中收藏的大神的博客