AC自动机-从树到图-T1
时间:2019-06-18
本文章向大家介绍AC自动机-从树到图-T1,主要包括AC自动机-从树到图-T1使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
AC自动机已经足够棒了。
但是,好像有时还是要TLE的。
一般的AC自动还是比较好,如果在某些情况下还是会被卡掉,像是这个水题
考试的感觉
我看到这个题后,我清清楚楚的知道,这是个AC自动机+栈。
经过一番努力,把AC自动机打了出来,然后略加修饰,把栈补在里面。
我一复制,一粘贴,更高兴(?)了,过样例了,噫,我要A了。
但是我又随便写了一坨字符进去,然后就,不对了~~~~~~
最后也没调出来,后来我想想,好像是没恢复搜索栈顶元素。
我太菜了。
---以上都是废话---
更改的过程
我T60之后,想了一会,去查了Trie图,但是比较难受。
后来是有大神告诉我,可以用简单的办法构建部分Tire图,优化后就可以AC惹
但是我囿于万恶的板子,一直TLE。
唔啊啊啊啊!
我改了一会,建好图,信心满满,然后又……T了?
后来我又想,又问了几个大佬「没有得到满意的答复」
最后我充满疑惑的看到了我的while,好像不是那么回事
void ffind(){ int j=0; ACauto *p=root; sta[t++]=root; while(st[j]){ int k=st[j]-'a'; while(p!=root && p->s[k]==NULL) p=p->next; p=p->s[k]; sta[t++]=p; if(p==NULL) p=root; ACauto *l=p; while(l!=root){//这个while if(l->len!=0){ t-=l->len; p=sta[t-1]; break; } l=l->next; } j++; } }
我为什么要反复去找一个字符呢?
于是删掉while,改成if,AC。
额,一个while卡我6000ms。
分析一下,
我写的板子来自上面的两道题,有重复字符,互为子串的也有
而本题明确说明:N个字符串中无互相包含的
所以这句话就是没有意义的,它反复去找出现这个字符的地方,浪费了众多时间
而我们只需要找上一个字符出现之后的这一个字符就可以
所以,改成if更加正确。
void ffind(){ int j=0; ACauto *p=root; sta[t++]=root; while(st[j]){ int k=st[j]-'a'; while(p!=root && p->s[k]==NULL) p=p->next; p=p->s[k]; sta[t++]=p; if(p==NULL) p=root; ACauto *l=p; if(l->len!=0){ t-=l->len; p=sta[t-1]; } j++; } }
全代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define N 101010 5 using namespace std; 6 struct ACauto{ 7 ACauto *next,*s[26]; 8 int len; 9 char ch; 10 }s[100*N];int tot=0; 11 ACauto *newACauto(){ 12 tot++; 13 return &s[tot-1]; 14 } 15 ACauto *root=newACauto(); 16 char st[N],ch[N]; 17 ACauto *q[10000000];int f=0,e=0; 18 bool empty(){ 19 if(f==e)return true; 20 return false; 21 } 22 void push(ACauto *x){ 23 e++; 24 q[e]=x; 25 } 26 ACauto* front(){ 27 f++; 28 return q[f]; 29 } 30 void add(const char *c){ 31 int j=0; 32 ACauto *i=root; 33 while(c[j]){ 34 int k=c[j]-'a'; 35 if(i->s[k]==NULL) i->s[k]=newACauto(); 36 i=i->s[k]; 37 i->ch=c[j]; 38 j++; 39 } 40 i->len=j; 41 } 42 void build(){ 43 root->next=NULL; 44 push(root); 45 while(!empty()){ 46 ACauto *n=front(); 47 for(int i=0;i<26;i++){ 48 if(n->s[i]!=NULL){ 49 if(n==root) n->s[i]->next=root; 50 else{ 51 ACauto *p=n->next; 52 while(p!=NULL){ 53 if(p->s[i]!=NULL){ 54 n->s[i]->next=p->s[i]; 55 // n->s[i]=p; 56 break; 57 } 58 p=p->next; 59 } 60 if(p==NULL) n->s[i]->next=root; 61 } 62 push(n->s[i]); 63 } 64 else{ 65 if(n==root) 66 n->s[i]=root; 67 else 68 n->s[i]=n->next->s[i]; 69 } 70 } 71 } 72 } 73 ACauto *sta[N]; 74 int t=0; 75 void pour(){ 76 for(int i=0;i<t;i++){ 77 putchar(sta[i]->ch); 78 } 79 puts(""); 80 } 81 void ffind(){ 82 int j=0; 83 ACauto *p=root; 84 sta[t++]=root; 85 while(st[j]){ 86 int k=st[j]-'a'; 87 while(p!=root && p->s[k]==NULL) p=p->next; 88 p=p->s[k]; 89 sta[t++]=p; 90 if(p==NULL) p=root; 91 ACauto *l=p; 92 if(l->len!=0){ 93 //pour();//cout<<t<<" "<<l->len<<endl; 94 t-=l->len; 95 p=sta[t-1]; 96 } 97 j++; 98 } 99 } 100 int _n=0; 101 void prerun(){ 102 for(int i=0;i<26;i++){ 103 root->s[i]=new ACauto(); 104 root->s[i]->ch='a'+i; 105 } 106 } 107 int main(){ 108 prerun(); 109 scanf("%s",st); 110 scanf("%d",&_n); 111 for(int i=1;i<=_n;i++){ 112 scanf("%s",ch); 113 add(ch); 114 } 115 build(); 116 ffind(); 117 for(int i=1;i<t;i++)putchar(sta[i]->ch); 118 puts(""); 119 return 0; 120 }
原文地址:https://www.cnblogs.com/kalginamiemeng/p/11038676.html
- libmemcached编译安装报错解决记录
- 解决网站静态缓存后WP-PostViews插件不计数的问题
- Haproxy安装部署文档及多配置文件管理方案
- ASM 翻译系列第三十四弹:ASM磁盘组重要属性介绍
- 博客集成Hitokoto·一言经典语句功能
- 博客网页导致电脑CPU飙升的问题解决记录
- 恢复WordPress分类目录的别名链接形式
- 替代crontab,统一定时任务管理系统cronsun简介
- 小网站最简单实用的动静分离优化方案
- Haproxy进阶管理:命令行控制后端节点上下线
- 网站集成打字震动特效JS代码改进版
- Linux基础知识之文件隐藏属性
- Linux系统chmod误操作目录权限恢复方法
- 结合VBS,实现批处理自动以管理员身份执行
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- elastic search 如何将yellow 状态变为green健康状态
- All clients has disconnected from. You can graceful shutdown now., dubbo version: , current host
- Failed to instantiate org.mybatis.spring.SqlSessionTemplate Constructor threw exception
- 护网之Linux应急处理操作手册
- 对新版安全狗学习
- redis key的删除策略及LRU的实现
- 护网Linux应急处置操作手册-Tools篇
- 加密,编码三问
- 我是怎么挖掘yii2反序列化0day的
- yii2反序列化后续
- 线程基础三问——猫眼真题
- V8引擎对Array.prototype.push的源码实现
- HTTPS三问—腾讯真题
- 神锁离线版插件的安全设计
- 数据分析入门系列教程-数据清洗