• [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 }
    >这里<
    Miemeng真的蒻
  • 相关阅读:
    TWaver3D直线、曲线、曲面的绘制
    react开发教程(六)React与DOM
    java Web开发实现手机拍照上传到服务器
    手把手教你从零写一个简单的 VUE--模板篇
    file_get_contents函数获取不到数据的一种情况
    Windows系统下批处理快速创建WIFI
    操作系统题库之简答题部分(个人整理,附带答案)
    回溯到底是个什么东西(含有大量经典例题加详细分析)
    到底什么是dp思想(内含大量经典例题,附带详细解析)
    一次性弄懂到底什么叫做分治思想(含有大量经典例题,附带详细解析)
  • 原文地址:https://www.cnblogs.com/kalginamiemeng/p/11038676.html
Copyright © 2020-2023  润新知