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 ;
}

>这里<

最新文章

  1. C语言数据类型取值范围
  2. hdu 4025 2011上海赛区网络赛E 压缩 ***
  3. centos 6 initctl
  4. Android开发之注解式框架ButterKnife的使用
  5. 有关line-height的见解
  6. ABAP提示信息对话框
  7. NSDate 总结日期操作
  8. CFLAGS/CPPFLAGS/CXXFLAGS in Makefile介绍
  9. 在 Java 项目中解压7Zip特殊压缩算法文件
  10. ASP.NET AJAX 创建类
  11. div流加载
  12. 【django之modelform】
  13. 数据加密--详解 RSA加密算法 原理与实现
  14. oh-my-zsh: 让终端飞
  15. Git 配置用户名、密码
  16. Excel基本操作
  17. maven添加jetty插件,同时运行多个实例
  18. Java基本语法---个人参考资料
  19. 【总结 】550,535,553 Mail from must equal authorized user— jenkins(hudson) email163邮箱和26邮箱成功配置总结
  20. PowerDesigner 同步Name到Comment 及 同步 Comment 到Name

热门文章

  1. 为什么python2.7中用Process创建子进程的语句之前必须加#if
  2. JAVA Synchronized (二)
  3. Java泛型简明教程
  4. STL--lower_bound()&amp;upper_bound();
  5. redis简介、安装、配置和数据类型
  6. E20180423-hm
  7. (水题)洛谷 - P1093 - 奖学金
  8. 合作网络(Corporative Network )并查集+路径压缩
  9. python实现选择排序
  10. 洛谷 P1199 三国游戏