[BZOJ3940][Usaco2015 Feb]Censoring-AC自动机-从树到图

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 }
>这里<

 

posted @ 2019-06-18 14:35  Miemeng_麦蒙  阅读(209)  评论(0编辑  收藏  举报

小麦在雨中,蒙蒙的雾气

麦蒙不想有人骚扰他,如果有必要 联系 QQ:1755601414

如果你嫌广告大,那就喷我吧,不是博客园的锅。