zoukankan      html  css  js  c++  java
  • AC自动机

    光看课件觉得脑洞挺大的,,,然而模板在手天下我有

    • 先来道模板题

         hdu2222

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 #define maxn 1000005
     5 char t[maxn],s[maxn];
     6 int tot,trie[maxn][26],mark[maxn],fail[maxn],Q[maxn];
     7 
     8 void add(char *t){
     9     int p=0,i;
    10     for(int i=1;t[i];i++){
    11         if(!trie[p][t[i]-'a'])trie[p][t[i]-'a']=++tot;
    12         p=trie[p][t[i]-'a'];
    13     }
    14     mark[p]++;
    15 }
    16 void build(){
    17     int head=0,tail=0;
    18     Q[++tail]=0;
    19     while(head<tail){
    20         int x=Q[++head];
    21         for(int i=0;i<26;i++){
    22             if(trie[x][i]){
    23                 Q[++tail]=trie[x][i];
    24                 fail[trie[x][i]]=x?trie[fail[x]][i]:0;
    25             }
    26             else trie[x][i]=trie[fail[x]][i];        
    27         }
    28     } 
    29 }
    30 int main(){
    31     int T;
    32     scanf("%d",&T);
    33     while(T--){
    34         memset(trie,0,sizeof(trie));
    35         memset(mark,0,sizeof(mark));
    36         tot=0;
    37         int n;
    38         scanf("%d",&n);
    39         for(int i=1;i<=n;i++){
    40             scanf("%s",t+1);
    41             add(t);
    42         }
    43         build();
    44         scanf("%s",s+1);
    45         int p=0,ans=0;
    46         for(int i=1;s[i];i++){
    47             p=trie[p][s[i]-'a'];
    48             int pp=p;
    49             while(pp&&mark[pp]){
    50                 ans+=mark[pp];
    51                 mark[pp]=0;
    52                 pp=fail[pp];
    53             }
    54         }
    55         printf("%d
    ",ans);
    56     }
    57     return 0;
    58 }

       数组版,简单对称和谐,以后trie树也这么写:P

       难懂的地方就是build函数建trie图,fail[trie[x][i]]=trie[fail[x]][i]保证了后缀相同的性质。pery大爷教育道,当trie[x][i]不存在时直接把它链到trie[fail[x]][i]上来保证复杂度

    • 刷模板的时候总会碰到坑B题

         hdu2896

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define maxn 100005
     4 #define maxc 128
     5 char t[255],s[10005];
     6 int tot,num,total,trie[maxn][maxc],vis[510],mark[maxn],fail[maxn],Q[maxn];
     7 void add(char *t,int id){
     8     int p=0;
     9     for(int i=1;t[i];i++){
    10         if(!trie[p][t[i]-32])trie[p][t[i]-32]=++tot;
    11         p=trie[p][t[i]-32];
    12     }
    13     mark[p]=id;
    14 }
    15 void build(){
    16     int head=0,tail=0;
    17     Q[++tail]=0;
    18     while(head<tail){
    19         int x=Q[++head];
    20         for(int i=0;i<128;i++){
    21             if(trie[x][i]){
    22                 Q[++tail]=trie[x][i];
    23                 fail[trie[x][i]]=x?trie[fail[x]][i]:0;
    24             }
    25             else trie[x][i]=trie[fail[x]][i];
    26         }
    27     }
    28 }
    29 void solve(char *s,int id){
    30     int p=0;
    31     bool flag=false;
    32     for(int i=1;s[i];i++){
    33         p=trie[p][s[i]-32];
    34         int pp=p;
    35         while(pp){
    36             if(mark[pp]){    
    37                 flag=true;
    38                 vis[mark[pp]]=1;
    39             }
    40             pp=fail[pp];
    41         }
    42     }
    43     if(flag){
    44         total++;
    45         printf("web %d:",id);
    46         for(int i=1;i<=500;i++)
    47             if(vis[i]){
    48                 vis[i]=0;
    49                 printf(" %d",i);
    50             }
    51         printf("
    ");
    52     }
    53 }
    54 int main(){
    55     int n;
    56     scanf("%d",&n);
    57     for(int i=1;i<=n;i++){
    58         scanf("%s",t+1);
    59         add(t,i);
    60     }
    61     build();
    62     scanf("%d",&n);
    63     for(int i=1;i<=n;i++){
    64         scanf("%s",s+1);
    65         solve(s,i);
    66     }
    67     printf("total: %d
    ",total);
    68     return 0;
    69 } 

       R/M了12次,boom,,,于是引发了trie数组第一维开多大的讨论也就是对于给定的数据范围,不同的节点到底有多少个。。。毕竟不是所有题都像usaco某题一样给出了不同的节点的最大个数的

    • 前两道都是noip之前为了应付膜你赛做的,觉得自己已经基本掌握,,,然而接下来就要打脸了

         bzoj2434

    #include<stdio.h>
    #define maxn 100005
    char str[maxn];
    int cnt,v[maxn],next[maxn],first[maxn],hav[maxn],hanext[maxn],hafirst[maxn];
    int time,tot,trie[maxn][26],q[maxn],fail[maxn],in[maxn],out[maxn],pos[maxn],fa[maxn],ans[maxn],BIT[maxn<<1];
    void add(int st,int end){
        v[++cnt]=end;
        next[cnt]=first[st];
        first[st]=cnt;
    }
    void update(int yooo,int x){
        for(int i=yooo;i<=time;i+=(i&(-i)))
            BIT[i]+=x;
    }
    int query(int yooo){
        int sum=0;
        for(int i=yooo;i;i-=(i&(-i)))
            sum+=BIT[i];
        return sum;
    }
    void build(){
        int head=0,tail=0;
        q[++tail]=0;
        while(head<tail){
            int x=q[++head];
            for(int i=0;i<26;i++){
                if(trie[x][i]){
                    q[++tail]=trie[x][i];
                    fail[trie[x][i]]=x?trie[fail[x]][i]:0;
                }
                else trie[x][i]=trie[fail[x]][i];
            }
        }
    }
    void dfs(int sss){
        in[sss]=++time;
        for(int e=first[sss];e;e=next[e])
            dfs(v[e]);
        out[sss]=++time;
    }
    void solve(){
        int p=0,id=0;
        for(int i=1;str[i];i++){
            if(str[i]=='P'){
                id++;
                for(int e=hafirst[id];e;e=hanext[e]){
                    int lol=pos[hav[e]];
                    ans[e]=query(out[lol])-query(in[lol]-1);
                }
            }
            else if(str[i]=='B')update(in[p],-1),p=fa[p];//
            else p=trie[p][str[i]-'a'],update(in[p],1);
        }
    }
    int main(){
        freopen("1.in","r",stdin);
        int m,x,y;
        scanf("%s",str+1);
        int p=0,id=0;
        for(int i=1;str[i];i++){
            if(str[i]=='P')pos[++id]=p;
            else if(str[i]=='B')p=fa[p];
            else{
                if(!trie[p][str[i]-'a'])trie[p][str[i]-'a']=++tot;
                fa[trie[p][str[i]-'a']]=p;
                p=trie[p][str[i]-'a'];
            }
        }
        build();
        for(int i=1;i<=tot;i++)
            add(fail[i],i);
        dfs(0);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            hav[i]=x;
            hanext[i]=hafirst[y];
            hafirst[y]=i;
        }
        solve();
        for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
        return 0;
    }

       fail树太神,第二个临接表也超美,但是发现自己树状数组和dfs序都不太6的样子,尤其是dfs序,out=++time和out=time的区别还是不卵懂,或者说根本没有区别QAQ

       以666结尾,然后去拉车。。。

  • 相关阅读:
    171. Excel Sheet Column Number (Easy)
    349. Intersection of Two Arrays (Easy)
    453. Minimum Moves to Equal Array Elements (Easy)
    657. Judge Route Circle (Easy)
    CSS笔记
    保存页面状态
    UI开发总结
    ubuntu 下配置munin
    反向代理配置
    JavaScript 高级程序设计第二版
  • 原文地址:https://www.cnblogs.com/Ngshily/p/4978974.html
Copyright © 2011-2022 走看看