zoukankan      html  css  js  c++  java
  • 洛谷 P3808 【模板】AC自动机(简单版)洛谷 P3796 【模板】AC自动机(加强版)

    https://www.cnblogs.com/gtarcoder/p/4820560.html

    每个节点的后缀指针fail指针指向:

    例如he,she,his,hers的例子(见蓝书P214):

    7号点表示串his,将其头部去掉得到is但不存在该节点,再次将其头部去掉得到s,存在该节点,因此7号的后缀指针指向表示s的3号

    5号点表示串she,将其头部去掉得到he,存在该节点,因此5号的后缀指针指向表示he的2号

    从根节点到节点P可以得到一个字符串S,节点P的前缀指针定义为 指向树中出现过的S的最长后缀(不能等于S)

    可以将trie上所有不存在的边u--(ch)-->v都补全为其fail指针指向的同类型边(f[u]--(ch)-->v'得到u--(ch)-->v')。(减少特判且方便递推)

    每个节点的lst,与fail的区别在于,其指向的点表示的字符串一定是原来字符串集合中某一个完整的串(或空串),而fail则只要求原集合中某串的前缀即可

    P3808中:由于只计算“出现过的”,所以某个算过贡献后要赋为0

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<queue>
      5 using namespace std;
      6 char *s[1001000],tttt[2000100],*sp=tttt,s2[1000100];
      7 int n;
      8 //namespace AC
      9 //{
     10 //    int ch[1001000][26],sum[1001000],f[1001000],root,mem,lst[1000100];
     11 //    void insert(char *x)
     12 //    {
     13 //        if(!root)    root=++mem;
     14 //        int now=root,u;
     15 //        for(;*x;x++)
     16 //        {
     17 //            u=*x-'a';
     18 //            if(!ch[now][u])    ch[now][u]=++mem;
     19 //            now=ch[now][u];
     20 //        }
     21 //        sum[now]++;
     22 //    }
     23 //    void build()
     24 //    {
     25 //        int c,t,u,v;
     26 //        queue<int> q;
     27 //        f[root]=root;
     28 //        for(c=0;c<26;c++)
     29 //        {
     30 //            u=ch[root][c];
     31 //            if(u)    {f[u]=root;q.push(u);lst[u]=root;}
     32 //        }
     33 //        while(!q.empty())
     34 //        {
     35 //            t=q.front();q.pop();
     36 //            for(c=0;c<26;c++)
     37 //            {
     38 //                u=ch[t][c];
     39 //                if(!u)    {ch[t][c]=ch[f[t]][c];continue;}
     40 //                q.push(u);
     41 //                v=f[t];
     42 //                while(v!=root&&!ch[v][c])    v=f[v];
     43 //                f[u]=ch[v][c];
     44 //                lst[u]=sum[u]?f[u]:lst[f[u]];
     45 //            }
     46 //        }
     47 //    }
     48 //    void search(char *x)
     49 //    {
     50 //        int j=root;
     51 //        for(;*x;x++)
     52 //        {
     53 //            c=*x-'a';
     54 //            if(sum[c])
     55 //        }
     56 //    }
     57 //}
     58 //注释掉的是root任意值的情况,未完成,以下程序认为root为0号点
     59 namespace AC
     60 {
     61     int ch[1001000][26],sum[1001000],f[1001000],mem,lst[1000100];
     62     void insert(char *x)
     63     {
     64         int now=0,u;
     65         for(;*x;x++)
     66         {
     67             u=*x-'a';
     68             if(!ch[now][u])    ch[now][u]=++mem;
     69             now=ch[now][u];
     70         }
     71         sum[now]++;
     72     }
     73     void build()
     74     {
     75         int c,t,u;
     76         queue<int> q;
     77         f[0]=0;
     78         for(c=0;c<26;c++)
     79         {
     80             u=ch[0][c];
     81             if(u)    {f[u]=0;q.push(u);lst[u]=0;}
     82         }
     83         while(!q.empty())
     84         {
     85             t=q.front();q.pop();
     86             for(c=0;c<26;c++)
     87             {
     88                 u=ch[t][c];
     89                 if(!u)    {ch[t][c]=ch[f[t]][c];continue;}
     90                 q.push(u);
     91                 f[u]=ch[f[t]][c];
     92                 lst[u]=sum[f[u]]?f[u]:lst[f[u]];
     93             }
     94         }
     95     }
     96     int ans;
     97     void get_ans(int j)
     98     {
     99         while(j)
    100         {
    101             ans+=sum[j];
    102             sum[j]=0;
    103             j=lst[j];
    104         }
    105     }
    106     int count(char *x)
    107     {
    108         ans=0;
    109         int j=0,c;
    110         for(;*x;x++)
    111         {
    112             c=*x-'a';
    113             j=ch[j][c];
    114             get_ans(j);
    115         }
    116         return ans;
    117     }
    118 }
    119 int main()
    120 {
    121     int i;
    122     scanf("%d",&n);
    123     for(i=1;i<=n;i++)
    124     {
    125         s[i]=sp;scanf("%s",s[i]);sp+=strlen(s[i])+1;
    126         AC::insert(s[i]);
    127     }
    128     AC::build();
    129     scanf("%s",s2);
    130     printf("%d",AC::count(s2));
    131     return 0;
    132 }

    P3796

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<queue>
      5 #include<vector>
      6 #include<map>
      7 #include<string>
      8 using namespace std;
      9 char *s[160],tttt[20000],*sp,s2[1000100];
     10 int n;
     11 namespace AC
     12 {
     13     int ch[20000][26],sum[20000],f[20000],mem,lst[20000],ans[20000];
     14     void clear()
     15     {
     16         int i,j;
     17         for(i=0;i<=mem;i++)
     18         {
     19             for(j=0;j<26;j++)    ch[i][j]=0;
     20             sum[i]=f[i]=lst[i]=ans[i]=0;
     21         }
     22         mem=0;
     23     }
     24     int insert(char *x)
     25     {
     26         int now=0,u;
     27         for(;*x;x++)
     28         {
     29             u=*x-'a';
     30             if(!ch[now][u])    ch[now][u]=++mem;
     31             now=ch[now][u];
     32         }
     33         sum[now]++;
     34         return now;
     35     }
     36     void build()
     37     {
     38         int c,t,u;
     39         queue<int> q;
     40         f[0]=0;
     41         for(c=0;c<26;c++)
     42         {
     43             u=ch[0][c];
     44             if(u)    {f[u]=0;q.push(u);lst[u]=0;}
     45         }
     46         while(!q.empty())
     47         {
     48             t=q.front();q.pop();
     49             for(c=0;c<26;c++)
     50             {
     51                 u=ch[t][c];
     52                 if(!u)    {ch[t][c]=ch[f[t]][c];continue;}
     53                 q.push(u);
     54                 f[u]=ch[f[t]][c];
     55                 lst[u]=sum[f[u]]?f[u]:lst[f[u]];
     56             }
     57         }
     58     }
     59     void get_ans(int j)
     60     {
     61         while(j)
     62         {
     63             ans[j]+=sum[j];
     64             j=lst[j];
     65         }
     66     }
     67     void work(char *x)
     68     {
     69         int j=0,c;
     70         for(;*x;x++)
     71         {
     72             c=*x-'a';
     73             j=ch[j][c];
     74             get_ans(j);
     75         }
     76     }
     77 }
     78 int pos[20000];
     79 int a1,anss;
     80 int main()
     81 {
     82     int i;
     83     while(1)
     84     {
     85         scanf("%d",&n);
     86         if(n==0)    break;
     87         AC::clear();
     88         sp=tttt;
     89         for(i=1;i<=n;i++)
     90         {
     91             s[i]=sp;scanf("%s",s[i]);sp+=strlen(s[i])+1;
     92             pos[i]=AC::insert(s[i]);
     93         }
     94         AC::build();
     95         scanf("%s",s2);
     96         AC::work(s2);a1=anss=0;
     97         for(i=1;i<=n;i++)
     98             if(AC::ans[pos[i]]>a1)
     99                 a1=AC::ans[pos[i]];
    100         for(i=1;i<=n;i++)
    101             if(AC::ans[pos[i]]==a1)
    102                 anss++;
    103         printf("%d
    ",a1);
    104         for(i=1;i<=n;i++)
    105             if(AC::ans[pos[i]]==a1)
    106                 printf("%s
    ",s[i]);
    107     }
    108     return 0;
    109 }
  • 相关阅读:
    《Django By Example》第十二章(终章) 中文 翻译 (个人学习,渣翻)
    《Django By Example》第十一章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第十章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第九章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第八章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第五章 中文 翻译 (个人学习,渣翻)
    我的superui开源后台bootstrap开发框架
    LayoutInflater 总结
    Android屏幕分辨率概念(dp、dip、dpi、sp、px)
    android studio安装问题
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8810666.html
Copyright © 2011-2022 走看看