HDU 2222【AC自动机模板】
来源:互联网 发布:淘宝详情页950 编辑:程序博客网 时间:2024/05/21 23:32
题意:
第一行输入测试数据的组数,然后输入一个整数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
阅读全文
0 0
- 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自动机 模板
- HDU 2222【AC自动机模板】
- 【AC自动机详解+入门模板】HDU 2222
- 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自动机模板题
- C语言-线性表
- Matlab2017安装
- 684. Redundant Connection
- LintCode 循环单词
- Qt入门-应用程序类QApplication
- HDU 2222【AC自动机模板】
- ServletContext 获取上下文对象
- OpenCV—椭圆拟合fitEllipse
- 大数据学习路线
- spring could 之服务的注册与发现(Eureka)
- 发布npm时遇到的两个小问题,解决方法
- 彻底明白 position及z-index的用法 static ,absolute ,relative
- C#中跨线程访问控件问题解决方案
- python数据分析系列教程——python(pandas)读写csv文件