AC自动机已经足够棒了。

但是,好像有时还是要TLE的。

一般的AC自动还是比较好,如果在某些情况下还是会被卡掉,像是这个水题


考试的感觉

我看到这个题后,我清清楚楚的知道,这是个AC自动机+栈。

经过一番努力,把AC自动机打了出来,然后略加修饰,把栈补在里面。

我一复制,一粘贴,更高兴(?)了,过样例了,噫,我要A了。

但是我又随便写了一坨字符进去,然后就,不对了~~~~~~

最后也没调出来,后来我想想,好像是没恢复搜索栈顶元素。

我太菜了。

---以上都是废话---


更改的过程

我T60之后,想了一会,去查了Trie图,但是比较难受。

后来是有大神告诉我,可以用简单的办法构建部分Tire图,优化后就可以AC惹

但是我囿于万恶的板子,一直TLE。

唔啊啊啊啊!

我改了一会,建好图,信心满满,然后又……T了?

后来我又想,又问了几个大佬「没有得到满意的答复」

最后我充满疑惑的看到了我的while,好像不是那么回事

void ffind(){
int j=;
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!=){
t-=l->len;
p=sta[t-];
break;
}
l=l->next;
}
j++;
}
}

我为什么要反复去找一个字符呢?

于是删掉while,改成if,AC。

额,一个while卡我6000ms。

分析一下,

我写的板子来自上面的两道题,有重复字符,互为子串的也有

而本题明确说明:N个字符串中无互相包含的

所以这句话就是没有意义的,它反复去找出现这个字符的地方,浪费了众多时间

而我们只需要找上一个字符出现之后的这一个字符就可以

所以,改成if更加正确。

void ffind(){
int j=;
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!=){
t-=l->len;
p=sta[t-];
}
j++;
}
}

全代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#define N 101010
using namespace std;
struct ACauto{
ACauto *next,*s[];
int len;
char ch;
}s[*N];int tot=;
ACauto *newACauto(){
tot++;
return &s[tot-];
}
ACauto *root=newACauto();
char st[N],ch[N];
ACauto *q[];int f=,e=;
bool empty(){
if(f==e)return true;
return false;
}
void push(ACauto *x){
e++;
q[e]=x;
}
ACauto* front(){
f++;
return q[f];
}
void add(const char *c){
int j=;
ACauto *i=root;
while(c[j]){
int k=c[j]-'a';
if(i->s[k]==NULL) i->s[k]=newACauto();
i=i->s[k];
i->ch=c[j];
j++;
}
i->len=j;
}
void build(){
root->next=NULL;
push(root);
while(!empty()){
ACauto *n=front();
for(int i=;i<;i++){
if(n->s[i]!=NULL){
if(n==root) n->s[i]->next=root;
else{
ACauto *p=n->next;
while(p!=NULL){
if(p->s[i]!=NULL){
n->s[i]->next=p->s[i];
// n->s[i]=p;
break;
}
p=p->next;
}
if(p==NULL) n->s[i]->next=root;
}
push(n->s[i]);
}
else{
if(n==root)
n->s[i]=root;
else
n->s[i]=n->next->s[i];
}
}
}
}
ACauto *sta[N];
int t=;
void pour(){
for(int i=;i<t;i++){
putchar(sta[i]->ch);
}
puts("");
}
void ffind(){
int j=;
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!=){
//pour();//cout<<t<<" "<<l->len<<endl;
t-=l->len;
p=sta[t-];
}
j++;
}
}
int _n=;
void prerun(){
for(int i=;i<;i++){
root->s[i]=new ACauto();
root->s[i]->ch='a'+i;
}
}
int main(){
prerun();
scanf("%s",st);
scanf("%d",&_n);
for(int i=;i<=_n;i++){
scanf("%s",ch);
add(ch);
}
build();
ffind();
for(int i=;i<t;i++)putchar(sta[i]->ch);
puts("");
return ;
}

>这里<

T1订正记-AC自动机-从树到图的更多相关文章

  1. hdu 4117 GRE Words (ac自动机 线段树 dp)

    参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...

  2. hdu 4117 -- GRE Words (AC自动机+线段树)

    题目链接 problem Recently George is preparing for the Graduate Record Examinations (GRE for short). Obvi ...

  3. 【BZOJ2434】阿狸的打字机(AC自动机,树状数组)

    [BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ...

  4. 【BZOJ2434】【NOI2011】阿狸的打字机(AC自动机,树状数组)

    [BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ...

  5. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  6. NOI 2011 阿狸的打字机(AC自动机+主席树)

    题意 https://loj.ac/problem/2444 思路 ​多串匹配,考虑 \(\text{AC}\) 自动机.模拟打字的过程,先建出一棵 \(\text{Trie}\) 树,把它变成自动机 ...

  7. BZOJ2905: 背单词 AC自动机+fail树+线段树

    $zjq$神犇一眼看出$AC$自动机 $Orz$ 直接就讲做法了 首先对每个串建出$AC$自动机 将$fail$树找到 然后求出$dfs$序 我们发现一个单词 $S_i$是$S_j$的子串当且仅当$S ...

  8. BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树

    Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...

  9. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

随机推荐

  1. Python3中使用PyMongo的方法详解

    前言 本文主要给大家介绍的是关于在Python3使用PyMongo的方法,分享出来供大家参考学习,下面话不多说了,来一起看看详细介绍: MongoDB存储 在这里我们来看一下Python3下Mongo ...

  2. 【转】nose-parameterized是Python单元测试框架实现参数化的扩展

    原文地址: http://www.cnblogs.com/fnng/p/6580636.html 相对而言,Python下面单元测试框架要弱上少,尤其是Python自带的unittest测试框架,不支 ...

  3. 【旧文章搬运】Windows内核常见数据结构(驱动相关)

    原文发表于百度空间,2008-7-24========================================================================== 这些是驱动中 ...

  4. 启动和测试oracle是否安装成功

    转自:https://www.cnblogs.com/justdo-it/articles/5112576.html 测试步骤1:请执行操作系统级的命令:tnsping orcl 测试步骤 2:请执行 ...

  5. (4)ASP.NET Core 中间件

    1.前言 整个HTTP Request请求跟HTTP Response返回结果之间的处理流程是一个请求管道(request pipeline).而中间件(middleware)则是一种装配到请求管道以 ...

  6. 洛谷 - P1379 - 八数码难题 - bfs

    https://www.luogu.org/problemnew/show/P1379 #include <bits/stdc++.h> using namespace std; #def ...

  7. python iteration 迭代

    可迭代的类型:list,tuple,dict,str,bytes,bytearray等 一.怎么判断一个对象是否可迭代 >>> from collections import Ite ...

  8. SpringBoot的配置文件加载顺序以及如何获取jar包里的资源路径

    一.读取配置文件的四种方式 这四种配置文件放置方式的读取优先级依次递减,具体可以查看官方文档. 1.1jar包同级目录下的config文件夹里的配置文件 其实我以前就见过这种方式了,只是不知道怎么做的 ...

  9. iOS NSUserDefaults [setValue:forKey:] [setObject:forKey:] <Objc> setValue(_,forKey:) set(_,forKey) <Swift 3>

    前者其实是NSObject都可以调用的KVC方法,后者才是NSUserDefaults的实例方法: 这里参数的类型是nullable id,但是我建议你在传null的时候慎重考虑,否则你的应用就可能面 ...

  10. 跟我一起玩Win32开发(14):用对话框作为主窗口

    前面我们在编写Win32应用程序的思路都是: 1.设计窗口类.2.注册窗口类.3.创建窗口.…… 然而,当我们接触控件以后, 会发现一个问题,我们在窗口上放置控件实在不好弄,而资源中的对话框具有图形编 ...