HDU 2222【AC自动机】
2017-10-26 21:32
323 查看
题意:
第一行输入测试数据的组数,然后输入一个整数n,接下来的n行每行输入一个单词。最后输入一个字符串,问在这个字符串中有多少个单词出现过。
#include <stdio.h> #include <stdlib.h> #include <string.h> struct Node { int cnt;//是否为该单词的最后一个结点 Node *fail;//失败指针 Node *next[26];//Trie中每个结点的各个节点 }*queue[500005];//队列,方便用BFS构造失败指针 char s[1000005];//主字符串 char keyword[55];//需要查找的单词 Node *root;//头结点 void Init(Node *root)//每个结点的初始化 { root->cnt=0; root->fail=NULL; for(int i=0;i<26;i++) root->next[i]=NULL; } void Build_trie(char *keyword)//构建Trie树 { Node *p,*q; int i,v; int len=strlen(keyword); for(i=0,p=root;i<len;i++) { v=keyword[i]-'a'; if(p->next[v]==NULL) { q=(struct Node *)malloc(sizeof(Node)); Init(q); p->next[v]=q;//结点链接 } p=p->next[v];//指针移动到下一个结点 } p->cnt++;//单词最后一个结点cnt++,代表一个单词 } void Build_AC_automation(Node *root) { int head=0,tail=0;//队列头、尾指针 queue[head++]=root;//先将root入队 while(head!=tail) { Node *p=NULL; Node *temp=queue[tail++];//弹出队头结点 for(int i=0;i<26;i++) { if(temp->next[i]!=NULL)//找到实际存在的字符结点 { //temp->next[i] 为该结点,temp为其父结点 if(temp==root)//若是第一层中的字符结点,则把该结点的失败指针指向root temp->next[i]->fail=root; else { //依次回溯该节点的父节点的失败指针直到某节点的next[i]与该节点相同, //则把该节点的失败指针指向该next[i]节点; //若回溯到 root 都没有找到,则该节点的失败指针指向 root p=temp->fail;//将该结点的父结点的失败指针给p while(p!=NULL) { if(p->next[i]!=NULL) { temp->next[i]->fail=p->next[i]; break; } p=p->fail; } //让该结点的失败指针也指向root if(p==NULL) temp->next[i]->fail=root; } queue[head++]=temp->next[i];//每处理一个结点,都让该结点的所有孩子依次入队 } } } } int query(Node *root) { //i为主串指针,p为模式串指针 int i,v,count=0; Node *p=root; int len=strlen(s); for(i=0;i<len;i++) { v=s[i]-'a'; //由失败指针回溯查找,判断s[i]是否存在于Trie树中 while(p->next[v]==NULL && p!=root) p=p->fail; p=p->next[v];//找到后p指针指向该结点 if(p==NULL)//若指针返回为空,则没有找到与之匹配的字符 p=root; Node *temp=p;//匹配该结点后,沿其失败指针回溯,判断其它结点是否匹配 while(temp!=root)//匹配结束控制 { if(temp->cnt>=0)//判断该结点是否被访问 { count+=temp->cnt;//由于cnt初始化为 0,所以只有cnt>0时才统计了单词的个数 temp->cnt=-1;//标记已访问过 } else//结点已访问,退出循环 break; temp=temp->fail;//回溯 失败指针 继续寻找下一个满足条件的结点 } } return count; } int main() { int T,n; scanf("%d",&T); while(T--) { root=(struct Node *)malloc(sizeof(Node)); Init(root); scanf("%d",&n); for(int i=0;i<n;i++) { scanf("\n%s",keyword); Build_trie(keyword); } Build_AC_automation(root); scanf("\n%s",s); printf("%d\n",query(root)); } return 0; }
学习链接:
http://blog.csdn.net/liu940204/article/details/51347064相关文章推荐
- HDU 2222 AC自动机 解题报告
- HDU 2222 Keywords Search(我的第一道AC自动机,模板题)
- Hdu 2222 [AC自动机]
- AC自动机算法(hdu-2222)
- HDU2222 AC自动机模板
- HDU 2222 Keywords Search [AC自动机]
- hdu 2222 AC自动机
- HDU-2222 Keywords Search(AC自动机--模板题)
- AC自动机入门题(HDU 2222 + HDU 2896)
- HDU 2222 Keywords Search 【AC自动机模板】
- hdu 2222 Keywords Search(AC自动机模板)
- hdu 2222 AC自动机 first
- HDU 2222 Keywords Search(AC自动机模板)
- hdu 2222 Keywords Search----AC自动机
- 【AC自动机详解+入门模板】HDU 2222
- hdu 2222 ac自动机模板题
- HDU 2222 AC自动机 裸题
- hdu 2222 AC自动机 。。
- HDU--2222--Keywords Search--AC自动机
- 文章标题 HDU 2222 : Keywords Search (AC自动机模板)