AC自动机入门经典题目(两种表达方式)
Keywords Search
指针方式:
/* Keywords Search */
# include <iostream>
# include <stdio.h>
# include <string.h>
# include <string>
# include <cstdlib>
# include <ctime>
# include <cmath>
# include <cctype>
# include <vector>
# include <deque>
# include <queue>
# include <stack>
# include <climits>
# include <bitset>
# include <set>
# include <map>
using namespace std; # define N
# define INF 0x3f3f3f3f
# define lowbit(x)(x&(-x)) struct node
{
int cnt;
node *next[];
node *fail;
node(){
cnt=;
fail=NULL;
memset(next, NULL, sizeof(next));
}
};
node *root;
char s[], str[N];
int n; void init()
{
root = new node;
} void _Insert(char *ss)
{
int len = strlen(ss);
node *p=root;
for(int i=; i<len; i++ )
{
int t=ss[i]-'a';
if( p->next[t]==NULL )
p->next[t]=new node;
p=p->next[t];
}
p->cnt++;
} void Build_the_fail()
{
root -> fail = NULL;
//node *p=root;
queue<node*>q;
q.push(root); while( !q.empty() )
{
node *cur=q.front();
q.pop(); for(int i=; i<; i++ )
{
if( cur->next[i]!=NULL )
{
if( cur==root )
cur->next[i]->fail = root;
else
{
node *p=cur->fail;
while( p!=NULL )
{
if( p->next[i]!=NULL )
{
cur->next[i]->fail = p->next[i];
break;
} else
{
p = p -> fail;
}
}
if( p==NULL )
cur->next[i]->fail = root;
}
q.push(cur->next[i]);
}
}
}
} int query(char *str)
{
node *cur=root;
int pos;
int cont=;
int len=strlen(str);
for(int i=; i<len; i++ )
{
pos=str[i]-'a';
while( cur->next[pos]==NULL && cur!=root )
{
cur = cur->fail;
}
cur = cur->next[pos];
if( cur==NULL )
cur = root;
node *temp=cur;
while( temp!=root )
{
if( temp->cnt!=- )
{
cont += temp-> cnt;
temp -> cnt = -;
}
temp = temp -> fail;
}
}
return cont;
} int main()
{
int t;
scanf("%d", &t);
while( t-- )
{
init();
scanf("%d", &n);
for(int i=; i<n; i++ )
{
scanf("%s", s);
_Insert(s);
}
Build_the_fail();
scanf("%s", str);
printf("%d\n", query(str));
}
return ;
}
数组方式:
/* */
# include <iostream>
# include <algorithm>
# include <utility>
# include <memory>
# include <deque>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <list>
# include <vector>
# include <cassert>
# include <functional>
# include <bitset>
# include <cmath>
# include <cstdlib>
# include <climits>
# include <cstring>
# include <string>
using namespace std;
typedef long long ll; # define mem(a,b)(a,b,sizeof(a))
# define lowbit(x)(x&(-x))
# define lcm(a,b)(a*b/__gcd(a,b))
const ll mod=1e9+;
const int maxn=;
const double pi=acos(-1.0); struct ac_auto
{
int Next[maxn][], Fail[maxn], End[maxn];//Next[now][buf[i]-'a'] 是now节点存着buf[i]字符的子节点的编号
int L, root;//注意这是全局变量,L是编号,root是根节点 int newNode(){
for(int i=; i<; i++ )//26叉树
Next[L][i] = -;
End[L++] = ;
return L-;//返回节点编号
} void Initial(){
L=;
root = newNode();
} void Insert( char buf[] )
{
int len=strlen(buf);
int now = root;
for(int i=; i<len; i++ )
{
if( Next[now][buf[i]-'a'] == - )
Next[now][buf[i]-'a'] = newNode();//若子节点没有buf[i],则插入buf[i]
now = Next[now][buf[i]-'a'];//now是当前节点编号
}
End[now]++;//作为结束字符的编号+1,计算单词出现的次数
} void Build_the_fail()
{
queue<int>ans;
Fail[root] = root;//根节点的失败指针指向自己 for(int i=; i<; i++ )
{
if( Next[root][i]==- )
Next[root][i] = root;
else
{
Fail[Next[root][i]] = root;//根节点的子节点的失败指针指向根节点
ans.push(Next[root][i]);
}
} while( !ans.empty() )
{
int now = ans.front();
ans.pop(); for(int i=; i<; i++)
{
if( Next[now][i]==- )
Next[now][i] = Next[Fail[now]][i];//若buf[i]没有插入字典树,则将令其等于其父节点的失败指针指向的节点的子节点buf[i]字符所在的节点
else
{
Fail[Next[now][i]] = Next[Fail[now]][i];//若buf[i]已经插入,其失败指针就指向其父节点的失败指针指向的节点的子节点buf[i]所在的节点
ans.push(Next[now][i]);//
}
}
}
} int Query( char buf[] )
{
int now = root;//从根节点开始找,now初始化为root
int res = ;//结果
int len = strlen(buf); for(int i=; i<len; i++ )
{
now = Next[now][buf[i]-'a'];//当前节点的编号
int temp = now;
while( temp!=root )
{
res += End[temp];//只有找到单词最后一个字符所在位置End[temp]才会>0,否则为0,所以可以直接加
End[temp] = ;//加完后置为0
temp = Fail[temp];//拓展到失败指针指向的位置,继续找
}
}
return res;
}
}AC; const int MAXN = ;
int T, n;
char buf[MAXN]; int main()
{
ios::sync_with_stdio(false);
cin>>T;
while( T-- )
{
cin>>n;
AC.Initial();
for(int i=; i<n; i++ )
{
cin>>buf;
AC.Insert(buf);
}
AC.Build_the_fail();
cin>>buf;
cout<<AC.Query(buf)<<endl;
}
return ;
}
AC自动机入门经典题目(两种表达方式)的更多相关文章
- Assignment写作需要掌握的两种表达方式
在正式开始写Assignment之前都会进行文献检索和整理,选择适合Assignment选题的文献资料进行阅读和引用.对于文献中与自己的观点高度相关的参考资料要如何具体引用,而不造成抄袭或者增加文章的 ...
- layui中弹出层的两种表达方式
方式一: 定义js中定义html变量 方式二: 设置div :hidden:hidden 布局 数据表格自适应大小: 代码: <style> .btn-container { margin ...
- AC自动机入门
Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. KMP算法很好的解决了单模式匹配问题,如果有了字典树的基础,我们可以完美的结合二者解决多 ...
- hdu2222 KeyWords Search AC自动机入门题
/** 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:题意:给定N(N <= 10000)个长度不大于50的模式串,再给定一个长度为L ...
- JavaScript 函数的两种声明方式
1.函数声明的方式 JavaScript声明函数有两种选择:函数声明法,表达式定义法. 函数声明法 function sum (num1 ,num2){ return num1+num2 } 表达式定 ...
- POJ 2299-Ultra-QuickSort-线段树的两种建树方式
此题有两种建树方式! Description In this problem, you have to analyze a particular sorting algorithm. The algo ...
- Spring的核心api和两种实例化方式
一.spring的核心api Spring有如下的核心api BeanFactory :这是一个工厂,用于生成任意bean.采取延迟加载,第一次getBean时才会初始化Bean Applicatio ...
- Web APi之认证(Authentication)两种实现方式【二】(十三)
前言 上一节我们详细讲解了认证及其基本信息,这一节我们通过两种不同方式来实现认证,并且分析如何合理的利用这两种方式,文中涉及到的基础知识,请参看上一篇文中,就不再叙述废话. 序言 对于所谓的认证说到底 ...
- Android中BroadcastReceiver的两种注册方式(静态和动态)详解
今天我们一起来探讨下安卓中BroadcastReceiver组件以及详细分析下它的两种注册方式. BroadcastReceiver也就是"广播接收者"的意思,顾名思义,它就是用来 ...
随机推荐
- OpenSSL X509 Funtion
OpenSSL X509 Funtion 来源:https://blog.csdn.net/wanjie518/article/details/6570141 现有的证书大都采用X509规范, 主要同 ...
- Tomcat组件梳理--Catalina
Tomcat组件梳理--Catalina 1.定义和功能 Catalina是Tomcat的核心组件,是Servlet容器,Catalina包含了所有的容器组件,其他模块均为Catalina提供支撑.通 ...
- 自学Python编程的第\七天----------来自苦逼的转行人
2019-09-17-23:09:48 今天学的内容是有关小数据池的,学的有点懵逼,感觉越来越难学了,但是得坚持下去 明天学习下一个课程时,感觉要跟不上,看来明天得先看好几遍今天的内容 不然肯定会听的 ...
- ORACLE ASMLIB
ORACLE ASMLIB This blog post is more of a note for myself on configuring ASMLib. ASMLib is an opti ...
- 使用Blynk打造一款物联网产品
前言 一直以来想自己打造一款物联网产品. 围绕这个话题写过一些文章: 一辆树莓派可编程小车的问题 基于树莓派的积木化编程解决方案 物联网相关开源项目整理 物联网.开源硬件与开源社区 之前在一辆树莓派可 ...
- 折叠面板实现,上传文件进度条,三级联选择器,多级联选择器, 利用layui实现
首先贴出html代码 <form class="layui-form" action=""> <div class="layui-f ...
- css display block 和 inline
根据CSS规范的规定,每一个网页元素都有一个display属性,用于确定该元素的类型,每一个元素都有默认的display属性值,比如div元素,它的默认display属性值为“block”,成为“块级 ...
- echarts 如何在世界地图中绘制中国地图
1.导入 world.china.js 这个js是将world.js 文件 以及china.js文件进行合并 (网上一些中国地图勾勒的身份曲线感觉很飘 所以自己加工了一下china.js中的数据, ...
- 一些替代Xshell的软件推荐
FinalShell: 面附上一些截图和官方连接: 官网:http://www.hostbuf.com/ FinalShell是一体化的的服务器,网络管理软件,不仅是ssh客户端,还是功能强大的开发, ...
- CSS制作华为mate8手机模型示例
CSS制作华为mate8手机模型效果图 1.HTML代码 <!DOCTYPE html> <html> <head> <meta charset=" ...