666 专题五 AC自动机
Problem A.Keywords Search
d.n个关键字,1段描述,求描述中出现了多少关键字
s.
c.
/*
ac自动机模板
n个关键字,1段描述,求描述中出现了多少关键字
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std; struct Trie{
int next[][],fail[],end[];
int root,L;
int newnode(){
for(int i=;i<;i++)
next[L][i]=-;
end[L++]=;
return L-;
}
void init(){
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();
now=next[now][buf[i]-'a'];
}
end[now]++;
}
void build(){
queue<int>Q;
fail[root]=root;
for(int i=;i<;i++)
if(next[root][i]==-)
next[root][i]=root;
else{
fail[next[root][i]]=root;
Q.push(next[root][i]);
}
while(!Q.empty()){
int now=Q.front();
Q.pop();
for(int i=;i<;i++)
if(next[now][i]==-)
next[now][i]=next[fail[now]][i];
else{
fail[next[now][i]]=next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
int query(char buf[]){
int len=strlen(buf);
int now=root;
int res=;
for(int i=;i<len;i++){
now=next[now][buf[i]-'a'];
int temp=now;
while(temp!=root){
res+=end[temp];
end[temp]=;
temp=fail[temp];
}
}
return res;
}
void debug(){
for(int i=;i<L;i++){
printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
for(int j=;j<;j++)
printf("%2d",next[i][j]);
printf("]\n");
}
}
}; char buf[];
Trie ac; int main(){
int T;
int n;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
ac.init();
for(int i=;i<n;i++){
scanf("%s",buf);
ac.insert(buf);
}
ac.build();
scanf("%s",buf);
printf("%d\n",ac.query(buf));
}
return ;
}
Problem B.病毒侵袭
d.这题和上题差不多,要输出出现模式串的id,用end记录id就可以了。还有trie树的分支是128的
s.
c.
/*
ac自动机模板
n个关键字,1段描述,求描述中出现了多少关键字
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<set>
using namespace std; struct Trie{
int next[*][],fail[*],end[*];
int root,L;
int newnode(){
for(int i=;i<;i++)
next[L][i]=-;
end[L++]=-;
return L-;
}
void init(){
L=;
root=newnode();
}
void insert(char buf[],int id){
int len=strlen(buf);
int now=root;
for(int i=;i<len;i++){
if(next[now][buf[i]]==-)
next[now][buf[i]]=newnode();
now=next[now][buf[i]];
}
end[now]=id;
}
void build(){
queue<int>Q;
fail[root]=root;
for(int i=;i<;i++)
if(next[root][i]==-)
next[root][i]=root;
else{
fail[next[root][i]]=root;
Q.push(next[root][i]);
}
while(!Q.empty()){
int now=Q.front();
Q.pop();
for(int i=;i<;i++)
if(next[now][i]==-)
next[now][i]=next[fail[now]][i];
else{
fail[next[now][i]]=next[fail[now]][i];
Q.push(next[now][i]);
}
}
} set<int>myset; bool query(char buf[],int id){
myset.clear();
int len=strlen(buf);
int now=root; for(int i=;i<len;i++){
now=next[now][buf[i]];
int temp=now;
while(temp!=root){
if(end[temp]!=-){
myset.insert(end[temp]);
}
temp=fail[temp];
}
} if(!myset.empty()){
printf("web %d:",id);
for(set<int>::iterator it=myset.begin();it!=myset.end();++it){
printf(" %d",*it);
}
printf("\n");
return true;
}
return false;
}
void debug(){
for(int i=;i<L;i++){
printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
for(int j=;j<;j++)
printf("%2d",next[i][j]);
printf("]\n");
}
}
}; char buf[];
Trie ac; int main(){ int N,M;
int ans; while(~scanf("%d",&N)){
ac.init(); for(int i=;i<=N;++i){
scanf("%s",buf);
ac.insert(buf,i);
} ac.build(); scanf("%d",&M);
ans=;
for(int i=;i<=M;++i){
scanf("%s",buf);
if(ac.query(buf,i)){
++ans;
}
} printf("total: %d\n",ans); } return ;
}
Problem C.病毒侵袭持续中
d.这题的变化也不大,就是需要输出每个模式串出现的次数,查询的时候使用一个数组进行记录就可以了
s.
c.
/*
ac自动机模板
n个关键字,1段描述,求描述中出现了多少关键字
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std; char str[][]; struct Trie{
int next[*][],fail[*],end[*];
int root,L;
int newnode(){
for(int i=;i<;i++)
next[L][i]=-;
end[L++]=-;
return L-;
}
void init(){
L=;
root=newnode();
}
void insert(char buf[],int id){
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();
now=next[now][buf[i]-'A'];
}
end[now]=id;
}
void build(){
queue<int>Q;
fail[root]=root;
for(int i=;i<;i++)
if(next[root][i]==-)
next[root][i]=root;
else{
fail[next[root][i]]=root;
Q.push(next[root][i]);
}
while(!Q.empty()){
int now=Q.front();
Q.pop();
for(int i=;i<;i++)
if(next[now][i]==-)
next[now][i]=next[fail[now]][i];
else{
fail[next[now][i]]=next[fail[now]][i];
Q.push(next[now][i]);
}
}
} int sum[]; void query(char buf[],int N){
memset(sum,,sizeof(sum));
int len=strlen(buf);
int now=root; for(int i=;i<len;i++){
if(buf[i]<'A'||buf[i]>'Z'){
now=root;//如果用128个来建字典树的话,没有的字符应该是指向root吧?应该是。
continue;//(即下面的now=next[now][buf[i]]的值应该是root?)
//使用这种判断的开辟26个字符即可,节省空间
}
now=next[now][buf[i]-'A'];
int temp=now;
while(temp!=root){
if(end[temp]!=-){
++sum[end[temp]];
} temp=fail[temp];
}
} for(int i=;i<N;++i){
if(sum[i]>){
printf("%s: %d\n",str[i],sum[i]);
}
}
}
void debug(){
for(int i=;i<L;i++){
printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
for(int j=;j<;j++)
printf("%2d",next[i][j]);
printf("]\n");
}
}
}; char buf[];
Trie ac; int main(){ int N; while(~scanf("%d",&N)){
ac.init();
for(int i=;i<N;i++){
scanf("%s",str[i]);
ac.insert(str[i],i);
}
ac.build();
scanf("%s",buf); ac.query(buf,N);
}
return ;
}
666 专题五 AC自动机的更多相关文章
- 「kuangbin带你飞」专题十七 AC自动机
layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...
- [专题总结]AC自动机
其实前面的模板也不是1A,我在题库里提前做过,也不必在意罚时,刚开始我在做别的专题 裸模板我就不说了,各个博客讲解的很明白 void insert(string s){ ,len=s.size(); ...
- [专题汇总]AC自动机
1.The 2011 ACM-ICPC Asia Dalian Regional Contest ZOJ 3545 Rescue the Rabbit 简单的AC自动机+状压DP, 状态DP[nod ...
- HDU 4511 小明系列故事——女友的考验 (AC自动机+DP)
小明系列故事——女友的考验 Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total ...
- AC自动机专题
AC自动机简介:KMP是用于解决单模式串匹配问题, AC自动机用于解决多模式串匹配问题. 精华:设这个节点上的字母为C,沿着他父亲的失败指针走,直到走到一个节点,他的儿子中也有字母为C的节点.然后把当 ...
- AC自动机 & Fail树 专题练习
Fail树就是AC自动机建出来的Fail指针构成的树. [bzoj3172][xsy1713]单词 题意 给定一些单词,求每个单词在所有单词里面的出现次数. 分析 构建Fail树,记录每个单词最后一个 ...
- 【AC自动机】专题总结
刷了一星期+的ac自动机的题目 做一个总结~ 我的ac自动机是之前省选的时候看老师给的一个网页上学的 由于找不到原文 就贴个转载的地址吧 - - http://hi.baidu.com/winterl ...
- 【专题】字符串专题小结(AC自动机 + 后缀自动机)
AC自动机相关: $fail$树: $fail$树上以最长$border$关系形成父子关系,我们定一个节点对应的串为根到该节点的路径. 对于任意一个非根节点$x$,定$y = fa_{x}$,那$y$ ...
- 专题训练之AC自动机
推荐博客:http://www.cnblogs.com/kuangbin/p/3164106.html AC自动机小结 https://blog.csdn.net/creatorx/article/d ...
随机推荐
- localStorag的一点见解
dot方法对localStorag方法进行键值操作 设值 localStorage.hello = 'world'; localStorage.zhangsan = 'lisi'; 取值: var v ...
- 了解Chrome扩展程序开发--摘抄
了解Chrome扩展程序开发 2018-01-11 边城到此莫若 鸡蛋君说前端 首先,我尝试来用简单几句话描述一下Chrome扩展程序: Chrome扩展主要用于对浏览器功能的增强,它强调与浏览器相结 ...
- [其他] 关于C语言中使用未声明函数的问题
在c语言中,碰到一个.c文件,无.h头文件,在另一.c文件调用函数时,并没有进行声明extern, 此时编译器不会报错,会默认去查找同名的函数,这样会存在一些问题,查了些资料,稍微总结了下: 总结: ...
- MongoDB存储引擎(上)——MMAPv1
3.0版本以前,MongoDB只有一个存储引擎——MMAP,MongoDB3.0引进了一个新的存储引擎——WiredTiger,同时对原有的MMAP引擎进行改进,产生MMAPv1存储引擎,并将其设置为 ...
- Day 4 Linux基础
Linux基础(指令篇) 一.Linux命令 1.Linux命令行的语法格式: 命令+选项+参数 命令:告诉Linux(UNIX)操作系统做(执行)什么. 选项:说明命令运行的方式(可以改变命令的功能 ...
- android导入项目出错之解决办法
导入android源码后,基本都有错误,R.java也不会自动生成,因为是第一次导入工程,工程有错R.java就不会自动生成了,工程有错误,当然模拟器就不能启动,也就看不到效果.随后网上找各种解决方法 ...
- 关于FileZilla Server的安装问题
网上很多FileZilla Server教程到最后一步在本机上测试访问成功就没了,实际上还是不完整的,一般情况下外网还是访问不了,外网访问同样很重要. 可能有点童鞋会说安装的时候防火墙提示的时候我也点 ...
- iOS 读书笔记 第一章
1.确定某个实例或类方法是否可用. 1)使用NSObject的类方法instancesRespondToSelector:来确定是否在该类的一个实例中存在一个特定的选择器. NSArray *arra ...
- react 起手式
http://blog.csdn.net/zhouzhiande/article/details/52349344 http://blog.csdn.net/zhouzhiande/article/d ...
- .net core mvc启动顺序以及主要部件2
原文:.net core mvc启动顺序以及主要部件2 前一篇提到WebHost.CreateDefaultBuilder(args)方法创建了WebHostBuilder实例,WebHostBuil ...