• 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结尾,然后去拉车。。。

  • 相关阅读:
    Windows Mobile开发环境搭建指南 (转)
    值得纪念的日子
    怎么让百度快速重新收录
    Window.ShowModalDialog使用手册
    取得MS SQL 数据库中每个表的记录数及空间占用情况
    SQL 列转行
    C#中double.tostring() C#保存小数位 C#四舍五入
    sql行转列 列数据不定 sql交叉报表实例
    discuz点歌台插件
    统计数据库中各个表和空间使用情况
  • 原文地址:https://www.cnblogs.com/Ngshily/p/4978974.html
Copyright © 2020-2023  润新知