HDU 2222 ACAM模板(AC自动机)
2017-08-10 00:33
561 查看
这里找到了两篇很nice的Trie树(作者Hackbuteer1)以及AC自动机(作者niushuai666)入门详解。博主写的可以说是非常用心了,一看就懂。
题意:给出N(<=10000)个单词(长度<=50)组成的字典。求串T(长度<=1e6)中出现了字典中的多少个单词。
题解:AC自动机裸题。所谓AC自动机就是Trie树加上了KMP的fail指针,而且是多模式的fail指针,意思就是说Trie图是有相同前缀的两个单词会有相同的一段root出发的路径,这个fail指针不再是KMP里某一个串的后缀和前缀相同并取最大,而是当前这个点得到的串的后缀和所有串中某个前缀相同且取最大。求这个fail就只要把KMP的过程改成广搜就行了,因为每个字符下一个状态可以是若干字符。。。每次把T中下一个字符考虑进来,通过fail指针转移到Trie图上的一个点上,然后统计root到这个点得到的串
的所有后缀的cnt(就是通过fail一点一点跳到根,把路径上的答案都统计起来。并把统计过的答案置为-1防止重复计数,同时fail跳到答案是-1的点表示这个点到根的答案已经统计过了,那么就提前停下来。)。
模板是我自己写的。。。可能比较丑。。。马上我会找一个好看的贴过来233
Code:
题意:给出N(<=10000)个单词(长度<=50)组成的字典。求串T(长度<=1e6)中出现了字典中的多少个单词。
题解:AC自动机裸题。所谓AC自动机就是Trie树加上了KMP的fail指针,而且是多模式的fail指针,意思就是说Trie图是有相同前缀的两个单词会有相同的一段root出发的路径,这个fail指针不再是KMP里某一个串的后缀和前缀相同并取最大,而是当前这个点得到的串的后缀和所有串中某个前缀相同且取最大。求这个fail就只要把KMP的过程改成广搜就行了,因为每个字符下一个状态可以是若干字符。。。每次把T中下一个字符考虑进来,通过fail指针转移到Trie图上的一个点上,然后统计root到这个点得到的串
的所有后缀的cnt(就是通过fail一点一点跳到根,把路径上的答案都统计起来。并把统计过的答案置为-1防止重复计数,同时fail跳到答案是-1的点表示这个点到根的答案已经统计过了,那么就提前停下来。)。
模板是我自己写的。。。可能比较丑。。。马上我会找一个好看的贴过来233
Code:
#include<bits/stdc++.h> using namespace std; const int MAX1 = 55; const int MAX2 = 1000050; char a[MAX1]; char b[MAX2]; struct ACAM { int id; int cnt; ACAM* fail; ACAM* nxt[26]; }; ACAM* root; void ACAM_Clear(ACAM* root){ for (int i=0;i<=25;i++){ if (root->nxt[i]!=NULL){ ACAM_Clear(root->nxt[i]); } } free(root); }; ACAM* ACAM_Create(int id){ ACAM* node = (ACAM*)(malloc(sizeof(ACAM))); node->cnt=0; node->fail = NULL; node->id =id; memset(node->nxt,0,sizeof(node->nxt)); return node; } void ACAM_Insert(ACAM* root,char* word){ ACAM* node = root; char* p = word; while (*p){ int id = *p-'a'; if (node->nxt[id]==NULL){ node->nxt[id] = ACAM_Create(id); } node = node->nxt[id]; p++; } node->cnt++; } ACAM* que[MAX2*10]; void ACAM_Build(ACAM* root){ int l=0,r=0; for (int i=0;i<=25;i++){ if (root->nxt[i]!=NULL){ root->nxt[i]->fail = root; for (int j=0;j<=25;j++){ if (root->nxt[i]->nxt[j]!=NULL){ root->nxt[i]->nxt[j]->fail = root; r++; que[r] = root->nxt[i]->nxt[j]; } } } } while (l<r){ l++; ACAM* q = que[l]; // printf("%d %c\n",l,q->id+'a'); while (q->fail!=root&&q->fail->nxt[q->id]==NULL){ q->fail = q->fail->fail; } if (q->fail->nxt[q->id]!=NULL){ q->fail = q->fail->nxt[q->id]; } // printf("%d fial = %c\n",l,q->fail->id+'a'); for (int i=0;i<=25;i++){ if (q->nxt[i]!=NULL){ q->nxt[i]->fail = q->fail; r++; que[r] = q->nxt[i]; } } } } int ACAM_Search(ACAM* root,char*word){ int ans=0; ACAM* node = root; char* p = word; while (*p){ // printf("%c\n",*p); int id = *p-'a'; while (node->nxt[id]==NULL&&node!=root){ node=node->fail; } if (node->nxt[id]!=NULL){ node = node->nxt[id]; } ACAM* temp = node; while (temp!=root&&temp->cnt!=-1){ ans+=temp->cnt; temp->cnt = -1; temp=temp->fail; } p++; } return ans; } void init(){ ACAM_Clear(root); root = ACAM_Create(-1); } void input(){ int n; scanf("%d",&n); while (n--){ scanf("%s",a); ACAM_Insert(root,a); } } void solve(){ ACAM_Build(root); scanf("%s",b); printf("%d\n",ACAM_Search(root,b)); } int main(){ int t; scanf("%d",&t); root = ACAM_Create(-1); while (t--){ init(); input(); solve(); } return 0; }
相关文章推荐
- 【HDU-2222】Keywords Search(AC自动机模板)
- hdu 2222 Keywords_ac自动机模板
- hdu 2222 ac自动机模板
- AC自动机 - 多模式串匹配问题的基本运用 + 模板题 --- HDU 2222
- hdu 2222 Keywords_ac自动机模板
- hdu 2222 AC自动机模板题
- hdu 2222(AC自动机模板)
- 【AC自动机详解+入门模板】HDU 2222
- hdu 2222 AC自动机模板题(指针版+数组版)
- HDU 2222 Keywords Search(我的第一道AC自动机,模板题)
- CUGB专题训练之数据结构:E - Keywords Search(HDU 2222 AC自动机经典入门模板题)
- HDU_2222 Keywords Search 【AC自动机模板题】【动态链表】
- HDU 2222 Keywords Search 【AC自动机(模板题)】
- HDU 2222 Keywords Search 【AC自动机模板】
- hdu 2222 Keywords Search(AC自动机模板)
- HDU 2222 Keywords Search(AC自动机模板)
- hdu 2222 AC自动机模板(非指针)
- HDU 2222 ac自动机入门模板题
- HDU 2222 Keywords Search(AC自动机模板)
- HDU 2222 AC自动机 模板