AC自动机模板
来源:互联网 发布:gre作文字数 知乎 编辑:程序博客网 时间:2024/04/30 23:57
#include<stdio.h>#include<string.h>#include<stdlib.h>#define kind 26const int MAXN = 10000000;struct node{ int count; //是否为单词最后一个节点 node *next[26];//Trie每个节点的26个子节点 node *fail; //失败指针};node *q[MAXN]; //队列,采用bfs 构造失败指针char keyword[55];//输入单词 模式串char str[1000010];// 需要查找的 主串int head,tail;//队列 头尾指针node *root;void insert(char *word,node *root){ int index,len; node *p = root,*newnode; len = strlen(word); for(int i=0 ;i < len ; i++ ) { index=word[i]-'a'; if(!p->next[index])//该字符节点不存在,加入Trie树中 { // 初始化 newnode 并 加入 Trie 树 newnode=(struct node *)malloc(sizeof(struct node)); for(int j=0;j<26;j++) newnode->next[j]=0; newnode->count=0;newnode->fail=0; p->next[index]=newnode; } p=p->next[index];//指针移动至下一层 } p->count++; //单词结尾 节点 count + 1 做标记 }void build_ac_automation(node *root){ head=0;tail=1; q[head]=root; node *temp,*p; while(head<tail)//bfs构造 Trie树的失败指针 { //算法类似 kmp ,这里相当于得到 next[]数组 //重点在于,匹配失败时,由fail指针回溯到正确的位置 temp=q[head++]; for(int i=0;i< 26 ;i ++) { if(temp->next[i])//判断实际存在的节点 { // root 下的第一层 节点 都 失败指针都 指向root if(temp==root)temp->next[i]->fail=root; else { //依次回溯 该节点的父节点的失败指针 //知道某节点的next[i]与该节点相同,则 //把该节点的失败指针指向该next[i]节点 //若回溯到 root 都没有找到,则该节点 //的失败指针 指向 root p=temp->fail;//temp 为节点的父指针 while(p){ if(p->next[i]){ temp->next[i]->fail=p->next[i]; break; } p=p->fail; } if(!p)temp->next[i]->fail=root; } //每处理一个点,就把它的所有儿子加入队列, //直到队列为空 q[tail++]=temp->next[i]; } } }}int query(node *root)//类似于 kmp算法。{//i为主串指针,p为匹配串指针 int i,cnt=0,index,len=strlen(str); node *p=root; for(i=0; i < len ;i ++) { index=str[i]-'a'; //由失败指针回溯寻找,判断str[i]是否存在于Trie树种 while( !p->next[index] && p != root)p=p->fail; p=p->next[index];//找到后 p 指向该节点 //指针回为空,则没有找到与之匹配的字符 if(!p)p=root;//指针重新回到根节点root,下次从root开始搜索Trie树 node *temp=p;//匹配该节点后,沿其失败指针回溯,判断其他节点是否匹配 while(temp != root )//匹配 结束控制 { if(temp->count>=0)//判断 该节点是否被访问 { //统计出现的单词个数cnt,由于节点不是单词结尾时count为0, //故 cnt+=temp->count; 只有 count >0时才真正统计了单词个数 cnt+=temp->count; temp->count=-1; //标记已访问 } else break;//节点已访问,退出循环 temp=temp->fail;//回溯失败指针继续寻找下一个满足条件的节点 } } return cnt;}int main(){ int i,t,n,ans; scanf("%d",&t); while(t--) { root=(struct node *)malloc(sizeof(struct node)); for(int j=0;j<26;j++) root->next[j]=0; root->fail=0; root->count=0; scanf("%d",&n); getchar(); for(i=0;i<n;i++) { gets(keyword); insert(keyword,root); } build_ac_automation(root); gets(str); ans=query(root); printf("%d\n",ans); } return 0;}
0 0
- 【AC自动机】AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板 hdu2222
- AC自动机模板
- AC自动机模板
- 数据结构--AC自动机--模板
- ac自动机模板
- AC自动机模板
- AC自动机模板
- hdu2222 ac自动机模板
- ac自动机模板。。。。。
- AC自动机模板 LA4670
- AC自动机模板
- HDU1106-排序
- storm学习(2) 进阶word_count 程序
- mysql、sqlserver、db2、oracle、hsql数据库获取数据库连接方法及分页函数
- 1, libyuv 编译 for android
- Git-Egit的安装
- AC自动机模板
- ConcurrentHashMap
- mysql 远程连接数据库的二种方法
- 欢迎使用CSDN-markdown编辑器
- 微信支付获取prepay_id以及回调地址
- 我国人口预计 15 年内是会逐渐分散在大中小城市,还是继续向大城市集中?我们应留在大城市发展吗?
- 创业那些年,我们一起走过的坑
- myeclipse安装svn,注销svn账号
- python字符串编码和转换